SlideShare a Scribd company logo
1 of 103
Download to read offline
CQRS and Event Sourcing
with MongoDB and PHP
About me
Davide Bellettini
● Developer at Onebip
● TDD addicted
@SbiellONE — about.bellettini.me
What is this talk about
A little bit of context
About Onebip
Mobile payment platform.
Start-up born in 2005,
acquired by Neomobile
group in 2011.
Onebip today:
- 70 countries
- 200+ carriers
- 5 billions potential users
LAMP stack
It all started with a Monolith
self-contained services communicating via REST
To a distributed system
First class modern NoSQL distributed dbs
Modern services
But the Monolith is still there
The problem
A reporting horror story
We need three new reports!
― Manager
Sure, no problem!
Deal with the legacy SQL schema
Deal with MongoDB
A little bit of queries here,
a little bit of map-reduce there
1 month later...
Reports are finally ready!
until...
Your queries are killing production!
― SysAdmin
Still not enough!
Heavy query optimization,
adding indexes
Let’s reuse data from other reports
(don’t do that)
DB is ok, reports delivered.
but then...
Houston, we have a problem. Reports are
not consistent (with other reports)
― Business guy
Mistakes
were
made
Lessons
learned
It’s hard to compare different data in a distributed
system splitted across multiple domains
#1
Avoid multiple sources of truth
Same words, different concepts across domains
#2
Ubiquitous language
Changing a report shouldn’t have side effects
#3
Fault tolerance to change
Most common solutions
#1
ETL + Map-Reduce
#2
Data Warehouse + Consultants
#3
Mad science (Yeppa!)
What we wanted
No downtime in production
Consistent across domains
Must have
A system elastic enough to extract any metric
Real time data
Nice to have
In DDD we found the light
CQRS and Event Sourcing
Command-query
responsibility segregation
(CQRS)
Commands
Anything that happens in one of your domains
is triggered by a command and generates one
or more events.
Order received -> payment sent -> Items queued
-> Confirmation email sent
Query
Generate read models from events depending
how data need to be actually used (by users
and other application internals)
Event Sourcing
The fundamental idea of Event Sourcing is that of ensuring
every change to the state of an application is captured in an
event object, and that these event objects are themselves
stored in the sequence they were applied.
― Martin Fowler
Starting from the beginning of time, you are
literally unrolling history to reach state in a
given time
Unrolling a stream of events
Idea #1
Every change to the state of your application is
captured in event object.
“UserLoggedIn”, “PaymentSent”, “UserLanded”
Idea #2
Events are stored in
the sequence they
were applied inside
an event store
Idea #3
Everything is an event. No more state.
Idea #4
One way to store data/events but potentially
infinite ways to read them.
A practical example
Tech ops, business control, monitoring,
accounting they all are interested in reading
data from different views.
Healthy NoSQL
You start with this
{
"_id": ObjectId("123"),
"username": "Flash",
"city": …,
"phone": …,
"email": …,
}
The more successful your company
is, the more people
…
The more people, the more views
With documental dbs it's magically easy to add new
fields to your collections.
Soon you might end up with
{
"_id": ObjectId("123"),
"username": "Flash",
"city": …,
"phone": …,
"email": …,
"created_at": …,
"updated_at": …,
"ever_tried_to_purchase_something": …,
"canceled_at": …,
"acquisition_channel": …,
"terminated_at": …,
"latest_purchase_date": …,
…
}
A bomb waiting to detonate
It’s impossible to keep adding state changes to your
documents and then expect to be able to extract them with
a single query.
Exploring
Tools
Event Store
● Engineered for event sourcing
● Supports projections
● By the father of CQRS (Greg Young)
● Great performances
http://geteventstore.com/
The bad
Based on Mono, still too unstable.
LevelWHEN
An event store built with Node.js and LevelDB
● Faster than light
● Completely custom, no tools to handle
aggregates
https://github.com/gabrielelana/levelWHEN
The known path
● PHP (any other language
would just do fine)
● MongoDB 2.2.x
Why MongoDB
Events are not relational
Scales well
Awesome aggregation framework
Hands on
Storing Events
Service |
 |
 [event payload] |
 |
Service --- Queue System <------------> API -> MongoDB
/ |
/ [event payload] |
/ |
Service |
The write architecture
Queues
Recruiter - https://github.com/gabrielelana/recruiter
MongoDB replica set
A MongoDB replica set with two logical dbs:
1. Event store where we would store events
2. Reporting DB where we would store
aggregates and final reports
Anatomy of an event 1/2
{
'_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9',
'type': 'an-event-type',
'data': {
'meta' : {
…
},
'payload' : {
…
}
}
}
Anatomy of an event 2/2
'meta' : {
'creation_date': ISODate("2014-21-11T00:00:01Z"),
'saved_date': ISODate("2014-21-11T00:00:02Z"),
'source': 'some-bounded-context',
'correlation_id': 'a-correlation-id'
},
'payload' : {
'user_id': '1234',
'animal': 'unicorn',
'colour': 'pink',
'purchase_date': ISODate("2014-21-11T00:00:00Z"),
'price': '20/fantaeuros'
}
Don’t trust the network: Idempotence
{
'_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9',
…
}
The _id field is actually defined client side and
ensures idempotence if an event is received
two times
Indexes
● Events collection is huge (~100*N documents)
● Use indexes wisely as they are necessary yet
expensive
● With suggested event structure:
{‘data.meta.created_at’: 1, type:1}
Benchmarking
How many events/second can you store?
Our machines were able to store roughly 150 events/sec.
This number can be greatly increased with dedicated IOPS,
more aggressive inserting policies, etc...
Final tips
● Use SSD on your storage machines
● Pay attention to write concerns (w=majority)
● Test your replica set fault tolerance
From events
to meaningful metrics
Sequential Projector -> Event Mapper -> Projection -> Aggregation
The event processing pipeline
A real life problem
What is the conversion rate of our registered
users?
#1 The registration event
{
'_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9',
'type': 'user-registered',
'data': {
'meta' : {
'save_date': ISODate("2014-21-11T00:00:09Z"),
'created_at': ISODate("2014-21-11T00:00:01Z"),
'source': 'core-domain',
'correlation_id': 'user-123456'
},
'payload' : {
'user_id': 123,
'username': 'flash',
'email': 'a-dummy-email@gmail.com',
'country': 'IT'
}
}
#2 The purchase event
{
'_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9',
'type': 'user-purchased',
'data': {
'meta' : {
'save_date': ISODate("2014-21-11T00:10:09Z"),
'created_at': ISODate("2014-21-11T00:10:01Z"),
'source': 'payment-gateway',
'correlation_id': 'user-123456'
},
'payload' : {
'user_id': 123,
'email': 'a-dummy-email@gmail.com',
'amount': 20,
'value': EUR,
'payment': 'credit_card',
'item': 'fluffy cat'
}
}
Sequential projector 1/2
[]->[x]->[]->[x]->[]->[]->[]->[]
|--------------| |------------|
|
|
|
|
---> Projector
Divides the stream of events into batches, filters events by
type and pass those of interest to the mapper
Sequential projector 2/2
● It’s a good idea to select fixed sizes batches to avoid
memory problems when you load your Cursor in memory
● Could be a long-running process selecting events as they
arrive in realtime
Event mapper 1/3
Translates event fields to the Read Model domain
Takes an event as input, applies a bunch of logic and will
return a list of Read Model fields.
Event mapper 2/3
Input event:
user-registered
Output:
$output = [
'user_id' => 123, // simply copied
'user_name' => 'flash', // simply copied
'email' => 'a-dummy-email@gmail.com', // simply copied
'registered_at' => "2014-21-11T00:00:01Z" // From the data.meta.created_at event field
];
Event mapper 3/3
Input event:
user-purchased
Output:
$output = [
'user_id' => 123, // simply copied
'email' => 'a-dummy-email@gmail.com', // simply copied
'purchased_at': "2014-21-11T00:10:01Z" // From the data.meta.created_at event field
];
Projection
Essentially it is your read model.
The data that the business is interested in.
The Projection after event #1
db.users_conversion_rate_projection.findOne()
{
'user_id': 123,
'user_name': 'flash',
'email': 'a-dummy-email@gmail.com',
'registered_at': "2014-21-11T00:00:01Z"
}
The Projection after event #2
{
'user_id': 123,
'user_name': 'flash',
'email': 'a-dummy-email@gmail.com',
'registered_at': "2014-21-11T00:00:01Z"
'purchased_at': "2014-21-11" // Added this field and rewrote others
}
The Projection collection{
'user_id': 123,
'user_name': 'flash',
'email': 'a-dummy-email@gmail.com',
'registered_at': "2014-21-11",
'purchased_at': "2014-21-11" // Added this field and rewrote others
}
{
'user_id': 456,
'user_name': 'batman',
'email': 'a-dummy-email@gmail.com',
'registered_at': "2014-21-11",
'purchased_at': "2014-21-11" // Added this field and rewrote others
}
{
'user_id': 789,
'user_name': 'superman',
'email': 'a-dummy-email@gmail.com',
'registered_at': "2014-21-12",
'purchased_at': "2014-21-12" // Added this field and rewrote others
}
The Projection - A few thoughts
Note that we didn't copy from events to projection
all the available fields. Just relevant ones.
From these two events we could have
generated infinite read models such as
● List all purchased products and related amounts for the
company buyers
● Map all sales and revenues for our accounting dept
● List transactions for the financial department
One way to write,
infinite ways to read!
The aggregation (1) - Total registered users
var registered = db.users_conversion_rate_projection.aggregate([
{
$match: {
"registered_at": { $gte: ISODate("2015-11-21"), $lte: ISODate("2015-11-22") }
}
},
{
$group: {
_id: { },
count: { $sum:1 }
}
}
]);
The aggregation (2) - User with a purchase
var purchased = db.users_conversion_rate_projection.aggregate([
{
$match: {
"registered_at": { $gte: ISODate("2015-11-21"), $lte: ISODate("2015-11-22") },
"purchased_at": { $exists: true }
}
},
{
$group: {
_id: { },
count: { $sum:1 }
}
}
]);
The aggregation (3) - Automate all the things
● You can easily create the aggregation framework statement
by composition abstracting the concept of Column.
● This way you can dynamically aggregate your projections
on (for example) an API requests.
● If your Projector is a long running process, your projections
will be updated to the second and you automagically get
realtime data.
Another events usage:
Business & Tech Monitoring
Beware of the beast!
No Silver Bullet
Events are expensive
They require a lot of TIME to be parsed
Events are expensive
You will end up with this billion size collection
(and counting)
Fixing wrong events is painful
Events are complex
Moving around events is
horribly painful
Actually it will make your life incredibly
difficult with hidden bugs and leaking
documentation.
Mongo won’t help you
Improvements
● Upgrade from MongoDB 2.2.x to 3.0.x
● Switch to WiredTiger storage engine to save
space
Credits
Based on a talk by Jacopo Nardiello
● Slides: http://bit.ly/es-nardiello-2014
● Video: https://vimeo.com/113370688
Q&A
@SbiellONE — about.bellettini.me
Thank you!

More Related Content

What's hot

Online Exam Management System(OEMS)
Online Exam Management System(OEMS)Online Exam Management System(OEMS)
Online Exam Management System(OEMS)PUST
 
Hostpital management system(srs)
Hostpital management system(srs)Hostpital management system(srs)
Hostpital management system(srs)maamir farooq
 
Hospital management synopsis
Hospital management synopsisHospital management synopsis
Hospital management synopsisYogeshDhamke2
 
Hospital mangement system report file
Hospital mangement system report fileHospital mangement system report file
Hospital mangement system report fileNausheen Hasan
 
Sql vs NoSQL
Sql vs NoSQLSql vs NoSQL
Sql vs NoSQLRTigger
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Traceoysteing
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Hermann Hueck
 
Building a Microservices-based ERP System
Building a Microservices-based ERP SystemBuilding a Microservices-based ERP System
Building a Microservices-based ERP SystemMongoDB
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain ExplainedJeremy Coates
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slidesmetsarin
 

What's hot (20)

Online Exam Management System(OEMS)
Online Exam Management System(OEMS)Online Exam Management System(OEMS)
Online Exam Management System(OEMS)
 
Hostpital management system(srs)
Hostpital management system(srs)Hostpital management system(srs)
Hostpital management system(srs)
 
Online quiz system
Online quiz systemOnline quiz system
Online quiz system
 
Hospital management synopsis
Hospital management synopsisHospital management synopsis
Hospital management synopsis
 
Date and time functions in mysql
Date and time functions in mysqlDate and time functions in mysql
Date and time functions in mysql
 
Srs
SrsSrs
Srs
 
JavaScript JQUERY AJAX
JavaScript JQUERY AJAXJavaScript JQUERY AJAX
JavaScript JQUERY AJAX
 
Hospital mangement system report file
Hospital mangement system report fileHospital mangement system report file
Hospital mangement system report file
 
Sql vs NoSQL
Sql vs NoSQLSql vs NoSQL
Sql vs NoSQL
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Trace
 
Sql select
Sql select Sql select
Sql select
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8
 
Building a Microservices-based ERP System
Building a Microservices-based ERP SystemBuilding a Microservices-based ERP System
Building a Microservices-based ERP System
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
Advanced sql
Advanced sqlAdvanced sql
Advanced sql
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain Explained
 
Hospital management system
Hospital management systemHospital management system
Hospital management system
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slides
 
Sql
SqlSql
Sql
 
SQL Overview
SQL OverviewSQL Overview
SQL Overview
 

Similar to CQRS and Event Sourcing with MongoDB and PHP

Flexible Event Tracking (Paul Gebheim)
Flexible Event Tracking (Paul Gebheim)Flexible Event Tracking (Paul Gebheim)
Flexible Event Tracking (Paul Gebheim)MongoSF
 
Building Microservices with Scala, functional domain models and Spring Boot -...
Building Microservices with Scala, functional domain models and Spring Boot -...Building Microservices with Scala, functional domain models and Spring Boot -...
Building Microservices with Scala, functional domain models and Spring Boot -...JAXLondon2014
 
#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...Chris Richardson
 
Log everything! @DC13
Log everything! @DC13Log everything! @DC13
Log everything! @DC13DECK36
 
NoSQL Deepdive - with Informix NoSQL. IOD 2013
NoSQL Deepdive - with Informix NoSQL. IOD 2013NoSQL Deepdive - with Informix NoSQL. IOD 2013
NoSQL Deepdive - with Informix NoSQL. IOD 2013Keshav Murthy
 
Snowplow: evolve your analytics stack with your business
Snowplow: evolve your analytics stack with your businessSnowplow: evolve your analytics stack with your business
Snowplow: evolve your analytics stack with your businessyalisassoon
 
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy NguyenGrokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy NguyenHuy Nguyen
 
Building Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchBuilding Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchMongoDB
 
Cloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload CourseCloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload Coursecloudbase.io
 
Our Data Ourselves, Pydata 2015
Our Data Ourselves, Pydata 2015Our Data Ourselves, Pydata 2015
Our Data Ourselves, Pydata 2015kingsBSD
 
The Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingThe Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingAndrea Saltarello
 
Snowplow - Evolve your analytics stack with your business
Snowplow - Evolve your analytics stack with your businessSnowplow - Evolve your analytics stack with your business
Snowplow - Evolve your analytics stack with your businessGiuseppe Gaviani
 
Tutorial: Building Your First App with MongoDB Stitch
Tutorial: Building Your First App with MongoDB StitchTutorial: Building Your First App with MongoDB Stitch
Tutorial: Building Your First App with MongoDB StitchMongoDB
 
Building a system for machine and event-oriented data - Data Day Seattle 2015
Building a system for machine and event-oriented data - Data Day Seattle 2015Building a system for machine and event-oriented data - Data Day Seattle 2015
Building a system for machine and event-oriented data - Data Day Seattle 2015Eric Sammer
 
Social Analytics with MongoDB
Social Analytics with MongoDBSocial Analytics with MongoDB
Social Analytics with MongoDBPatrick Stokes
 
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Chris Richardson
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Dan Robinson
 
The Future of Streaming: Global Apps, Event Stores and Serverless
The Future of Streaming: Global Apps, Event Stores and ServerlessThe Future of Streaming: Global Apps, Event Stores and Serverless
The Future of Streaming: Global Apps, Event Stores and ServerlessBen Stopford
 
Building a system for machine and event-oriented data - Velocity, Santa Clara...
Building a system for machine and event-oriented data - Velocity, Santa Clara...Building a system for machine and event-oriented data - Velocity, Santa Clara...
Building a system for machine and event-oriented data - Velocity, Santa Clara...Eric Sammer
 

Similar to CQRS and Event Sourcing with MongoDB and PHP (20)

Flexible Event Tracking (Paul Gebheim)
Flexible Event Tracking (Paul Gebheim)Flexible Event Tracking (Paul Gebheim)
Flexible Event Tracking (Paul Gebheim)
 
Building Microservices with Scala, functional domain models and Spring Boot -...
Building Microservices with Scala, functional domain models and Spring Boot -...Building Microservices with Scala, functional domain models and Spring Boot -...
Building Microservices with Scala, functional domain models and Spring Boot -...
 
#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...
 
Log everything! @DC13
Log everything! @DC13Log everything! @DC13
Log everything! @DC13
 
NoSQL Deepdive - with Informix NoSQL. IOD 2013
NoSQL Deepdive - with Informix NoSQL. IOD 2013NoSQL Deepdive - with Informix NoSQL. IOD 2013
NoSQL Deepdive - with Informix NoSQL. IOD 2013
 
Snowplow: evolve your analytics stack with your business
Snowplow: evolve your analytics stack with your businessSnowplow: evolve your analytics stack with your business
Snowplow: evolve your analytics stack with your business
 
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy NguyenGrokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
 
Building Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchBuilding Your First App with MongoDB Stitch
Building Your First App with MongoDB Stitch
 
Cloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload CourseCloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload Course
 
Our Data Ourselves, Pydata 2015
Our Data Ourselves, Pydata 2015Our Data Ourselves, Pydata 2015
Our Data Ourselves, Pydata 2015
 
The Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingThe Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event Sourcing
 
Meet with Meteor
Meet with MeteorMeet with Meteor
Meet with Meteor
 
Snowplow - Evolve your analytics stack with your business
Snowplow - Evolve your analytics stack with your businessSnowplow - Evolve your analytics stack with your business
Snowplow - Evolve your analytics stack with your business
 
Tutorial: Building Your First App with MongoDB Stitch
Tutorial: Building Your First App with MongoDB StitchTutorial: Building Your First App with MongoDB Stitch
Tutorial: Building Your First App with MongoDB Stitch
 
Building a system for machine and event-oriented data - Data Day Seattle 2015
Building a system for machine and event-oriented data - Data Day Seattle 2015Building a system for machine and event-oriented data - Data Day Seattle 2015
Building a system for machine and event-oriented data - Data Day Seattle 2015
 
Social Analytics with MongoDB
Social Analytics with MongoDBSocial Analytics with MongoDB
Social Analytics with MongoDB
 
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
Building and deploying microservices with event sourcing, CQRS and Docker (Ha...
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
 
The Future of Streaming: Global Apps, Event Stores and Serverless
The Future of Streaming: Global Apps, Event Stores and ServerlessThe Future of Streaming: Global Apps, Event Stores and Serverless
The Future of Streaming: Global Apps, Event Stores and Serverless
 
Building a system for machine and event-oriented data - Velocity, Santa Clara...
Building a system for machine and event-oriented data - Velocity, Santa Clara...Building a system for machine and event-oriented data - Velocity, Santa Clara...
Building a system for machine and event-oriented data - Velocity, Santa Clara...
 

More from Davide Bellettini

Presentazione UniversiBO (Ingegneria Informatica)
Presentazione UniversiBO (Ingegneria Informatica)Presentazione UniversiBO (Ingegneria Informatica)
Presentazione UniversiBO (Ingegneria Informatica)Davide Bellettini
 
Riunione aperta UniversiBO 08/05/2012
Riunione aperta UniversiBO 08/05/2012Riunione aperta UniversiBO 08/05/2012
Riunione aperta UniversiBO 08/05/2012Davide Bellettini
 
Framework di supporto allo sviluppo di applicazioni Web
Framework di supporto allo sviluppo di applicazioni WebFramework di supporto allo sviluppo di applicazioni Web
Framework di supporto allo sviluppo di applicazioni WebDavide Bellettini
 

More from Davide Bellettini (6)

Presentazione UniversiBO
Presentazione UniversiBOPresentazione UniversiBO
Presentazione UniversiBO
 
Presentazione UniversiBO (Ingegneria Informatica)
Presentazione UniversiBO (Ingegneria Informatica)Presentazione UniversiBO (Ingegneria Informatica)
Presentazione UniversiBO (Ingegneria Informatica)
 
pugBO #10 PSR e Composer
pugBO #10 PSR e ComposerpugBO #10 PSR e Composer
pugBO #10 PSR e Composer
 
Riunione aperta UniversiBO 08/05/2012
Riunione aperta UniversiBO 08/05/2012Riunione aperta UniversiBO 08/05/2012
Riunione aperta UniversiBO 08/05/2012
 
MyJOrganizer presentazione
MyJOrganizer presentazioneMyJOrganizer presentazione
MyJOrganizer presentazione
 
Framework di supporto allo sviluppo di applicazioni Web
Framework di supporto allo sviluppo di applicazioni WebFramework di supporto allo sviluppo di applicazioni Web
Framework di supporto allo sviluppo di applicazioni Web
 

Recently uploaded

%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Hararemasabamasaba
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 

Recently uploaded (20)

%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 

CQRS and Event Sourcing with MongoDB and PHP

  • 1. CQRS and Event Sourcing with MongoDB and PHP
  • 2. About me Davide Bellettini ● Developer at Onebip ● TDD addicted @SbiellONE — about.bellettini.me
  • 3. What is this talk about
  • 4. A little bit of context
  • 5. About Onebip Mobile payment platform. Start-up born in 2005, acquired by Neomobile group in 2011. Onebip today: - 70 countries - 200+ carriers - 5 billions potential users
  • 6. LAMP stack It all started with a Monolith
  • 7. self-contained services communicating via REST To a distributed system
  • 8. First class modern NoSQL distributed dbs Modern services
  • 9. But the Monolith is still there
  • 10. The problem A reporting horror story
  • 11. We need three new reports! ― Manager Sure, no problem!
  • 12. Deal with the legacy SQL schema
  • 13.
  • 15. A little bit of queries here, a little bit of map-reduce there
  • 19. Your queries are killing production! ― SysAdmin
  • 20. Still not enough! Heavy query optimization, adding indexes
  • 21. Let’s reuse data from other reports (don’t do that)
  • 22. DB is ok, reports delivered.
  • 24. Houston, we have a problem. Reports are not consistent (with other reports) ― Business guy
  • 25.
  • 28. It’s hard to compare different data in a distributed system splitted across multiple domains #1 Avoid multiple sources of truth
  • 29. Same words, different concepts across domains #2 Ubiquitous language
  • 30. Changing a report shouldn’t have side effects #3 Fault tolerance to change
  • 33. #2 Data Warehouse + Consultants
  • 36. No downtime in production Consistent across domains Must have
  • 37. A system elastic enough to extract any metric Real time data Nice to have
  • 38. In DDD we found the light
  • 39. CQRS and Event Sourcing
  • 41.
  • 42. Commands Anything that happens in one of your domains is triggered by a command and generates one or more events. Order received -> payment sent -> Items queued -> Confirmation email sent
  • 43. Query Generate read models from events depending how data need to be actually used (by users and other application internals)
  • 44. Event Sourcing The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied. ― Martin Fowler
  • 45. Starting from the beginning of time, you are literally unrolling history to reach state in a given time Unrolling a stream of events
  • 46. Idea #1 Every change to the state of your application is captured in event object. “UserLoggedIn”, “PaymentSent”, “UserLanded”
  • 47. Idea #2 Events are stored in the sequence they were applied inside an event store
  • 48. Idea #3 Everything is an event. No more state.
  • 49. Idea #4 One way to store data/events but potentially infinite ways to read them. A practical example Tech ops, business control, monitoring, accounting they all are interested in reading data from different views.
  • 51. You start with this { "_id": ObjectId("123"), "username": "Flash", "city": …, "phone": …, "email": …, }
  • 52. The more successful your company is, the more people … The more people, the more views
  • 53. With documental dbs it's magically easy to add new fields to your collections.
  • 54. Soon you might end up with { "_id": ObjectId("123"), "username": "Flash", "city": …, "phone": …, "email": …, "created_at": …, "updated_at": …, "ever_tried_to_purchase_something": …, "canceled_at": …, "acquisition_channel": …, "terminated_at": …, "latest_purchase_date": …, … }
  • 55. A bomb waiting to detonate It’s impossible to keep adding state changes to your documents and then expect to be able to extract them with a single query.
  • 57. Event Store ● Engineered for event sourcing ● Supports projections ● By the father of CQRS (Greg Young) ● Great performances http://geteventstore.com/ The bad Based on Mono, still too unstable.
  • 58. LevelWHEN An event store built with Node.js and LevelDB ● Faster than light ● Completely custom, no tools to handle aggregates https://github.com/gabrielelana/levelWHEN
  • 59. The known path ● PHP (any other language would just do fine) ● MongoDB 2.2.x
  • 60. Why MongoDB Events are not relational Scales well Awesome aggregation framework
  • 63. Service | | [event payload] | | Service --- Queue System <------------> API -> MongoDB / | / [event payload] | / | Service | The write architecture
  • 65. MongoDB replica set A MongoDB replica set with two logical dbs: 1. Event store where we would store events 2. Reporting DB where we would store aggregates and final reports
  • 66. Anatomy of an event 1/2 { '_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9', 'type': 'an-event-type', 'data': { 'meta' : { … }, 'payload' : { … } } }
  • 67. Anatomy of an event 2/2 'meta' : { 'creation_date': ISODate("2014-21-11T00:00:01Z"), 'saved_date': ISODate("2014-21-11T00:00:02Z"), 'source': 'some-bounded-context', 'correlation_id': 'a-correlation-id' }, 'payload' : { 'user_id': '1234', 'animal': 'unicorn', 'colour': 'pink', 'purchase_date': ISODate("2014-21-11T00:00:00Z"), 'price': '20/fantaeuros' }
  • 68. Don’t trust the network: Idempotence { '_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9', … } The _id field is actually defined client side and ensures idempotence if an event is received two times
  • 69. Indexes ● Events collection is huge (~100*N documents) ● Use indexes wisely as they are necessary yet expensive ● With suggested event structure: {‘data.meta.created_at’: 1, type:1}
  • 70. Benchmarking How many events/second can you store? Our machines were able to store roughly 150 events/sec. This number can be greatly increased with dedicated IOPS, more aggressive inserting policies, etc...
  • 71. Final tips ● Use SSD on your storage machines ● Pay attention to write concerns (w=majority) ● Test your replica set fault tolerance
  • 73. Sequential Projector -> Event Mapper -> Projection -> Aggregation The event processing pipeline
  • 74. A real life problem What is the conversion rate of our registered users?
  • 75. #1 The registration event { '_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9', 'type': 'user-registered', 'data': { 'meta' : { 'save_date': ISODate("2014-21-11T00:00:09Z"), 'created_at': ISODate("2014-21-11T00:00:01Z"), 'source': 'core-domain', 'correlation_id': 'user-123456' }, 'payload' : { 'user_id': 123, 'username': 'flash', 'email': 'a-dummy-email@gmail.com', 'country': 'IT' } }
  • 76. #2 The purchase event { '_id' : '3318c11e-fe60-4c80-a2b2-7add681492d9', 'type': 'user-purchased', 'data': { 'meta' : { 'save_date': ISODate("2014-21-11T00:10:09Z"), 'created_at': ISODate("2014-21-11T00:10:01Z"), 'source': 'payment-gateway', 'correlation_id': 'user-123456' }, 'payload' : { 'user_id': 123, 'email': 'a-dummy-email@gmail.com', 'amount': 20, 'value': EUR, 'payment': 'credit_card', 'item': 'fluffy cat' } }
  • 77. Sequential projector 1/2 []->[x]->[]->[x]->[]->[]->[]->[] |--------------| |------------| | | | | ---> Projector Divides the stream of events into batches, filters events by type and pass those of interest to the mapper
  • 78. Sequential projector 2/2 ● It’s a good idea to select fixed sizes batches to avoid memory problems when you load your Cursor in memory ● Could be a long-running process selecting events as they arrive in realtime
  • 79. Event mapper 1/3 Translates event fields to the Read Model domain Takes an event as input, applies a bunch of logic and will return a list of Read Model fields.
  • 80. Event mapper 2/3 Input event: user-registered Output: $output = [ 'user_id' => 123, // simply copied 'user_name' => 'flash', // simply copied 'email' => 'a-dummy-email@gmail.com', // simply copied 'registered_at' => "2014-21-11T00:00:01Z" // From the data.meta.created_at event field ];
  • 81. Event mapper 3/3 Input event: user-purchased Output: $output = [ 'user_id' => 123, // simply copied 'email' => 'a-dummy-email@gmail.com', // simply copied 'purchased_at': "2014-21-11T00:10:01Z" // From the data.meta.created_at event field ];
  • 82. Projection Essentially it is your read model. The data that the business is interested in.
  • 83. The Projection after event #1 db.users_conversion_rate_projection.findOne() { 'user_id': 123, 'user_name': 'flash', 'email': 'a-dummy-email@gmail.com', 'registered_at': "2014-21-11T00:00:01Z" }
  • 84. The Projection after event #2 { 'user_id': 123, 'user_name': 'flash', 'email': 'a-dummy-email@gmail.com', 'registered_at': "2014-21-11T00:00:01Z" 'purchased_at': "2014-21-11" // Added this field and rewrote others }
  • 85. The Projection collection{ 'user_id': 123, 'user_name': 'flash', 'email': 'a-dummy-email@gmail.com', 'registered_at': "2014-21-11", 'purchased_at': "2014-21-11" // Added this field and rewrote others } { 'user_id': 456, 'user_name': 'batman', 'email': 'a-dummy-email@gmail.com', 'registered_at': "2014-21-11", 'purchased_at': "2014-21-11" // Added this field and rewrote others } { 'user_id': 789, 'user_name': 'superman', 'email': 'a-dummy-email@gmail.com', 'registered_at': "2014-21-12", 'purchased_at': "2014-21-12" // Added this field and rewrote others }
  • 86. The Projection - A few thoughts Note that we didn't copy from events to projection all the available fields. Just relevant ones.
  • 87. From these two events we could have generated infinite read models such as ● List all purchased products and related amounts for the company buyers ● Map all sales and revenues for our accounting dept ● List transactions for the financial department
  • 88. One way to write, infinite ways to read!
  • 89. The aggregation (1) - Total registered users var registered = db.users_conversion_rate_projection.aggregate([ { $match: { "registered_at": { $gte: ISODate("2015-11-21"), $lte: ISODate("2015-11-22") } } }, { $group: { _id: { }, count: { $sum:1 } } } ]);
  • 90. The aggregation (2) - User with a purchase var purchased = db.users_conversion_rate_projection.aggregate([ { $match: { "registered_at": { $gte: ISODate("2015-11-21"), $lte: ISODate("2015-11-22") }, "purchased_at": { $exists: true } } }, { $group: { _id: { }, count: { $sum:1 } } } ]);
  • 91. The aggregation (3) - Automate all the things ● You can easily create the aggregation framework statement by composition abstracting the concept of Column. ● This way you can dynamically aggregate your projections on (for example) an API requests. ● If your Projector is a long running process, your projections will be updated to the second and you automagically get realtime data.
  • 92. Another events usage: Business & Tech Monitoring
  • 93. Beware of the beast! No Silver Bullet
  • 94. Events are expensive They require a lot of TIME to be parsed
  • 95. Events are expensive You will end up with this billion size collection (and counting)
  • 96. Fixing wrong events is painful
  • 98. Moving around events is horribly painful
  • 99. Actually it will make your life incredibly difficult with hidden bugs and leaking documentation. Mongo won’t help you
  • 100. Improvements ● Upgrade from MongoDB 2.2.x to 3.0.x ● Switch to WiredTiger storage engine to save space
  • 101. Credits Based on a talk by Jacopo Nardiello ● Slides: http://bit.ly/es-nardiello-2014 ● Video: https://vimeo.com/113370688
  • 102. Q&A