SlideShare a Scribd company logo
Matt Walters
@mateodelnorte
hi@iammattwalters.com
How to CQRS in Node
Eventually consistent architectures that scale
and grow.
It’s real. It works!
Former TechStars Co. CTO. Now consultant.
Built two businesses’ platforms from scratch using
CQRS in Node. Both large, distributed systems.
CQRS made both more maintainable and extendable.
Marketing platform crunched the Twitter firehose in
realtime. 3 Engineers managed around 20 services.
- GoChime.com
Bond Exchange with over $1.75B in trades. 6 engineers
managed around 40 services.
- Electronifie.com
Open Source my tooling and frameworks.
Other companies using them too!
(and I’ll tell you how)
That’s me ^^ !!
When to CQRS
• Realtime, reactive systems
• When preferring small, modular services
• When aiming for learning and growth
• When aiming to grow or eventually split teams
• Want ability to scale different parts of your
system separately
When not to CQRS
• Standalone, static sites
• Standalone, simple CRUD applications
What is CQRS?
First, a primer from history.
Bertrand Meyer, regarding object interfaces:
“Every method should either be a command that
performs an action, or a query that returns data to the
caller, but not both. In other words, Asking a question
should not change the answer.”
Long before CQRS was CQS:
Command Query Separation.
this guy
Some Type
doSomething() : void
getSomeStuff() : Stuff
Either change stuff<——
Or get stuff<——
CQS
Command-Query
Separation
doAndGetStuff() : Stuff Never both!
——————
Command-Query
Responsibility Segregation
A system-wide architecture that states - externally
facing subsystems (apps and apis) send commands to
perform actions which update the system’s state and
request queries to determine system’s state.
*Basically CQS on a system-wide scale. Calls between
services should change stuff, or get stuff. Never both.
CQRS
Command-Query
Responsibility Segregation
CQRS also denotes that queries and command
processing are provided by different subsystems.
Queries are made against a data store. Commands are
sent to and processed by services.
CQRS One more thing!
What is CQRS?
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
unidirectional flow
eventually consistent
Queries
Commands
the dance!
Events
How about a larger system?
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Queries
Commands
unidirectional flow
eventually consistent
the dance!
Events
What’s that dance you’re doing?
denormalizer
dbdenormalizer
dbdenormalizer
db
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
the dance!
chain reaction of events which play out as a result of an
incoming command.
each service subscribes to the events they care about
choreography!
(not orchestration)
Events
commands tell services
when an actor wants an action
clients send commands to instruct a service to do work
commands are sent asynchronously; fire and forget
commands are present-tense, directives: order.create
web app order-svc
order.create
commands are sent directly to a single receiving service
events tell the world
when you’re done
services publish to inform other services of work / actions performed,
and state updated
services publish (broadcast) events to any services
that wish to subscribe
events past-tense, describe what happened: order.created
order-svc fulfillment-svc
order.createdorder.created
order.created
order.created
Two types of services
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Two types of services
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Let’s focus on:
web-uiweb-uiweb-app
web
client
web-uiweb-uisvc
front end (an app’s perspective)
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Apps (and apis) still query a db to get the state of the system
Never directly modify the db they read from
Let’s focus on:
web-uiweb-uiweb-app
web
client
web-uiweb-uisvc
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Instead, apps (and apis) send commands instructing services to
perform an action
Apps expect their read only representation of system state will
eventually be updated in the denormalizer db
Let’s focus on:
front end (an app’s perspective)
Commands are sent over a reliable transport (rabbitmq, kafka,
zeromq, etc) to ensure delivery and eventual consistency
Let’s pick a transport!
rabbitmq
messaging that just works
• direct send to queue
• fanout / topic routing
• highly available
• highly performant
• used in financial exchanges,
industrial applications and more
• open source
• free
rabbitmq
messaging that just works
brew install rabbitmq
framework!minimalist
Let’s pick a
servicebus
super simple messaging in node
• direct send
• pub / sub / fanout / topic -routing
• simple to set up
• highly performant
• used in financial exchanges,
online advertising and more
• open source
• free
• perfect for creating microservices!
servicebus
super simple messaging in node
npm install servicebus —save
web-uiweb-uiweb-app
web
client
denormalizer
web-uiweb-uisvc
front end
denormalizer
dbdenormalizer
dbdenormalizer
db
What’s different?
Let’s focus on:
web-uiweb-uiweb-app
web-ui
web-uisvc
front end commands
denormalizer
dbdenormalizer
dbdenormalizer
db
How’s this work?
Let’s focus on:
Sending commands
from the front end
// web-app, onButtonClick. instead of updating db.
const bus = require('servicebus').bus();
bus.send(‘order.create', { 

order: {
userId: userId,
orderItems: items
}
});
web-uiweb-uiweb-app
web-ui
web-uisvc
// fire and forget.
command name
command itself
order.create command
Then what from the front end?
web-uiweb-uiweb-app
denormalizer
dbdenormalizer
dbdenormalizer
db
We wait.
• reactive / realtime:
• mongo oplog tailing (meteor)
• rethinkdb
• redis notifications
• couchdb
• graphQL
• polling
• non-realtime:
• product design: thanks! we’re processing your
order! check back later for updates!
queries!
We wait.
For the backend.
Choreography.
It’s eventually consistent!
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
front end
Let’s focus on:
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Let’s focus on:
back end
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Let’s focus on:
back end (a service’s perspective)
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
Let’s focus on:
Sample service.
web-uiweb-uiweb-app
web-ui
web-uisvc
command name
command object
// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
service publishes to the world when it’s done!
order.create command
order.created
event
Sample service.
web-uiweb-uiweb-app
web-ui
web-uisvc
listening for commands
performing business logic &
updating state// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
order.create command
order.created
event
completing atomic transaction and allowing error handling
back end (a downstream service’s perspective)
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
svc-2
Events
Events
Let’s focus on:
Same thing!
Sample downstream service.
web-uiweb-uiweb-app
web-ui
web-uisvc
// fulfillment-svc index.js
const bus = require(‘./bus’);
const fulfill = require(‘./lib/fulfill’);
bus.subscribe(‘order.created', (event) => {
fulfill(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.fulfilled’, order, () => {
event.handle.ack();
});
});
});
order.created
order.fulfilled
subscribe for events instead of
listening for commands
no different, from any other service!
Multiple handlers?
svc
Commands
svc-2
Events
svc-2
Events
servicebus-register-handlers
convention based event handler definition for
distributed services using servicebus.
automatically registers
event & command
handlers saved as
modules in folder
initialize at startup
servicebus-register-handlers
const bus = require(‘./lib/bus'); // instantiate servicebus instance
const config = require('cconfig')();
const log = require('llog');
const registerHandlers = require('servicebus-register-handlers');
registerHandlers({
bus: bus,
handleError: function handleError (msg, err) {
log.error('error handling %s: %s. rejecting message w/ cid %s and correlationId %s.', msg.type,
err, msg.cid, this.correlationId);
log.error(err);
msg.handle.reject(function () {
throw err;
});
},
path: './lib/handlers',
queuePrefix: 'my-svc-name'
});
initialize at startup:
provide initialized bus
define your error handling
path to your handlers
prefix to differentiate similar queues
servicebus-register-handlers
const log = require("llog");
module.exports.ack = true;
module.exports.queueName = 'my-service-name-order';
module.exports.routingKey = "order.create";
module.exports.listen = function (event, cb) {
log.info(`handling listened event of type ${event.type} with routingKey $
{this.routingKey}`);
/*
do something with your event
*/
cb();
};
each handler is a file
no params marks success.
pass back error to retry or fail.
callback based transactions!
differentiate queues
for different services
specify which commands or
events to listen or subscribe to
servicebus-register-handlers
super simple messaging in node
npm install servicebus-register-handlers —save
What about the ‘work’ part?
const log = require("llog");
module.exports.ack = true;
module.exports.queueName = 'my-service-name-order';
module.exports.routingKey = "order.create";
module.exports.listen = function (event, cb) {
log.info(`handling listened event of type ${event.type}
with routingKey ${this.routingKey}`);
/*
do something with your event
*/
cb();
};
// order-svc index.js
const bus = require(‘./bus’);
const create = require(‘./lib/create’);
bus.listen(‘order.create', (event) => {
create(event, (err, order) => {
if (err) return event.handle.reject();
bus.publish(‘order.created’, order, () => {
event.handle.ack();
});
});
});
these parts
What about the ‘work’ part?
That’s up to you!
Need an audit trail? Targeting finance? Consider event sourcing.
*and my framework, ‘sourced’
Depending on your problem, the right choice could be
mongoose and mongodb, a graph database, an in-memory data
structure, or even flat files.
CQRS makes no assertions about what technology you should
use, and in fact frees you to make a different decision for each
particular problem.
and depends on the problem you’re solving
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
bus.use() middleware
into bus message
pipeline. middleware can
act on incoming and/or
outgoing messages
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
packages outgoing
message data and
adds useful type,
timestamp, and
other properties
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
adds a correlationId
for tracing related
commands and events
through your system
But wait! There’s more!
servicebus middleware!
middleware can inspect and modify incoming
and outgoing messages
// ./lib/bus.js required as single bus instance used anywhere in service
const config = require('cconfig')();
const servicebus = require('servicebus');
const retry = require('servicebus-retry');
const bus = servicebus.bus({
url: config.RABBITMQ_URL
});
bus.use(bus.package());
bus.use(bus.correlate());
bus.use(retry({
store: new retry.RedisStore({
host: config.REDIS.HOST,
port: config.REDIS.PORT
})
}));
module.exports = bus;
now, every failed
message will retry
3 times if errors occur.
after that, the message
will automatically be
put on an error queue
for human inspection!
And more!
distributed tracing middleware!
var trace = require('servicebus-trace');
bus.use(trace({
serviceName: 'my-service-name',
store: new trace.RedisStore({
host: config.REDIS_HOST || 'localhost',
port: config.REDIS_PORT || 6379
})
}));
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Recapping Back End Services
back end services
web-uiweb-uiweb-app
svc
Commands
Events• Listen for commands and subscribe to events
• Performs business logic to process commands and events
• Update local state (optionally)
• Publish events to tell external services of updated state
Recapping:
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
back end
Recapping Back End Services
wat wat watwat
Wat!
is
a
denormalizer?
back end
What’s a denormalizer?
front end
• Just another back end service
• Has one job to do
• Subscribe to all events that the UI cares about
• Persist events in a format most efficient for the UI to view
• Completes the eventually consistent, unidirectional flow
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
Events
svc
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web
client
denormalizer
back end
What’s a denormalizer?
Events
front end
svc
Recapping the big picture.
denormalizer
dbdenormalizer
dbdenormalizer
db
web-uiweb-uiweb-app
web-uiweb-uiweb-api
web
client
mobile
client
denormalizer
svc-3
svc-2
web-uiweb-uisvc-1
Queries
Commands
unidirectional flow
eventually consistent
the dance!
Events
CQRS? That’s a myth!
Thanks!
We’ll sneak preview even more tooling for
easily building these systems in a future talk!
Matt Walters
github & twitter: @mateodelnorte
email: hi@iammattwalters.com
website: iammattwalters.com
rabbitmq.com
npmjs.com/package/servicebus
How to CQRS in Node
npmjs.com/package/servicebus-register-handlers
npmjs.com/package/servicebus-retry
npmjs.com/package/servicebus-trace

More Related Content

What's hot

Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM Talk
Patrick LaRoche
 
Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009John Allspaw
 
Rackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerRackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerMarc Cluet
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoringAlan Renouf
 
Backy - VM backup beyond bacula
Backy - VM backup beyond baculaBacky - VM backup beyond bacula
Backy - VM backup beyond bacula
Christian Theune
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현NAVER D2
 
Behind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling StorytimeBehind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling Storytime
SergeyChernyshev
 
Capacity Planning For LAMP
Capacity Planning For LAMPCapacity Planning For LAMP
Capacity Planning For LAMP
John Allspaw
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
Vivian S. Zhang
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
bobmcwhirter
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!
Chris Mills
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
bobmcwhirter
 
Packer, where DevOps begins
Packer, where DevOps beginsPacker, where DevOps begins
Packer, where DevOps begins
Jeff Hung
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"Chris Mills
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
POSSCON
 
Web optimization with service woker
Web optimization with service wokerWeb optimization with service woker
Web optimization with service woker
Chen-Tien Tsai
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
bobmcwhirter
 
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build SystemIntroduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
HubSpot Product Team
 
How to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - WebinarHow to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - Webinar
Common Sense
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존
동수 장
 

What's hot (20)

Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM Talk
 
Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009Operational Efficiency Hacks Web20 Expo2009
Operational Efficiency Hacks Web20 Expo2009
 
Rackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & PackerRackspace Hack Night - Vagrant & Packer
Rackspace Hack Night - Vagrant & Packer
 
vSphere APIs for performance monitoring
vSphere APIs for performance monitoringvSphere APIs for performance monitoring
vSphere APIs for performance monitoring
 
Backy - VM backup beyond bacula
Backy - VM backup beyond baculaBacky - VM backup beyond bacula
Backy - VM backup beyond bacula
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현
 
Behind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling StorytimeBehind the Scenes at LiveJournal: Scaling Storytime
Behind the Scenes at LiveJournal: Scaling Storytime
 
Capacity Planning For LAMP
Capacity Planning For LAMPCapacity Planning For LAMP
Capacity Planning For LAMP
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
Web versus Native: round 1!
Web versus Native: round 1!Web versus Native: round 1!
Web versus Native: round 1!
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Packer, where DevOps begins
Packer, where DevOps beginsPacker, where DevOps begins
Packer, where DevOps begins
 
Empowering the "mobile web"
Empowering the "mobile web"Empowering the "mobile web"
Empowering the "mobile web"
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
 
Web optimization with service woker
Web optimization with service wokerWeb optimization with service woker
Web optimization with service woker
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build SystemIntroduction to Packer and Suitcase: A Packer-based OS Image Build System
Introduction to Packer and Suitcase: A Packer-based OS Image Build System
 
How to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - WebinarHow to scale up, out or down in Windows Azure - Webinar
How to scale up, out or down in Windows Azure - Webinar
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존
 

Similar to How to CQRS in node: Eventually Consistent, Distributed Microservice Systems..

Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .Net
Richard Banks
 
HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...
Oleg Lobanov
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
Amazon Web Services
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
Get your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: BackendGet your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: Backend
Ackee
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices Architecture
Idan Fridman
 
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Agile Lietuva
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
CodeMill digital skills
 
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
confluent
 
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
Lightbend
 
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
Ludovic Piot
 
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Amazon Web Services
 
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
Susanne Kaiser
 
Integration in the age of DevOps
Integration in the age of DevOpsIntegration in the age of DevOps
Integration in the age of DevOps
Albert Wong
 
Reference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to KubernetesReference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to Kubernetes
Rakesh Gujjarlapudi
 
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You DrawNagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios
 
Micro service architecture
Micro service architectureMicro service architecture
Micro service architecture
uEngine Solutions
 
Microservices and Friends
Microservices and FriendsMicroservices and Friends
Microservices and Friends
Yun Zhi Lin
 
WinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release PipelinesWinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf
 
Evolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.jsEvolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.js
Steve Jamieson
 

Similar to How to CQRS in node: Eventually Consistent, Distributed Microservice Systems.. (20)

Architecting Microservices in .Net
Architecting Microservices in .NetArchitecting Microservices in .Net
Architecting Microservices in .Net
 
HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...HashiStack. To the cloud and beyond...
HashiStack. To the cloud and beyond...
 
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
(ARC402) Deployment Automation: From Developers' Keyboards to End Users' Scre...
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Get your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: BackendGet your mobile app in production in 3 months: Backend
Get your mobile app in production in 3 months: Backend
 
Vert.x for Microservices Architecture
Vert.x for Microservices ArchitectureVert.x for Microservices Architecture
Vert.x for Microservices Architecture
 
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
Vilius Lukošius - Decomposing distributed monolith with Node.js (WIX.com)
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
 
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
Modern Cloud-Native Streaming Platforms: Event Streaming Microservices with K...
 
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
How to build streaming data pipelines with Akka Streams, Flink, and Spark usi...
 
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
[Capitole du Libre] #serverless -  mettez-le en oeuvre dans votre entreprise...
 
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
Integrating Infrastructure as Code into a Continuous Delivery Pipeline | AWS ...
 
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
"Microservices Lessons Learned" talk at Voxxed Days Microservices, Paris
 
Integration in the age of DevOps
Integration in the age of DevOpsIntegration in the age of DevOps
Integration in the age of DevOps
 
Reference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to KubernetesReference architectures shows a microservices deployed to Kubernetes
Reference architectures shows a microservices deployed to Kubernetes
 
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You DrawNagios Conference 2014 - David Josephsen - Alert on What You Draw
Nagios Conference 2014 - David Josephsen - Alert on What You Draw
 
Micro service architecture
Micro service architectureMicro service architecture
Micro service architecture
 
Microservices and Friends
Microservices and FriendsMicroservices and Friends
Microservices and Friends
 
WinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release PipelinesWinOps Conf 2016 - Michael Greene - Release Pipelines
WinOps Conf 2016 - Michael Greene - Release Pipelines
 
Evolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.jsEvolution of a cloud start up: From C# to Node.js
Evolution of a cloud start up: From C# to Node.js
 

Recently uploaded

Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
UiPathCommunity
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 

Recently uploaded (20)

Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 

How to CQRS in node: Eventually Consistent, Distributed Microservice Systems..

  • 1. Matt Walters @mateodelnorte hi@iammattwalters.com How to CQRS in Node Eventually consistent architectures that scale and grow.
  • 2. It’s real. It works! Former TechStars Co. CTO. Now consultant. Built two businesses’ platforms from scratch using CQRS in Node. Both large, distributed systems. CQRS made both more maintainable and extendable. Marketing platform crunched the Twitter firehose in realtime. 3 Engineers managed around 20 services. - GoChime.com Bond Exchange with over $1.75B in trades. 6 engineers managed around 40 services. - Electronifie.com Open Source my tooling and frameworks. Other companies using them too! (and I’ll tell you how) That’s me ^^ !!
  • 3. When to CQRS • Realtime, reactive systems • When preferring small, modular services • When aiming for learning and growth • When aiming to grow or eventually split teams • Want ability to scale different parts of your system separately When not to CQRS • Standalone, static sites • Standalone, simple CRUD applications
  • 5. First, a primer from history. Bertrand Meyer, regarding object interfaces: “Every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.” Long before CQRS was CQS: Command Query Separation. this guy
  • 6. Some Type doSomething() : void getSomeStuff() : Stuff Either change stuff<—— Or get stuff<—— CQS Command-Query Separation doAndGetStuff() : Stuff Never both! ——————
  • 7. Command-Query Responsibility Segregation A system-wide architecture that states - externally facing subsystems (apps and apis) send commands to perform actions which update the system’s state and request queries to determine system’s state. *Basically CQS on a system-wide scale. Calls between services should change stuff, or get stuff. Never both. CQRS
  • 8. Command-Query Responsibility Segregation CQRS also denotes that queries and command processing are provided by different subsystems. Queries are made against a data store. Commands are sent to and processed by services. CQRS One more thing!
  • 10. How about a larger system? denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 Queries Commands unidirectional flow eventually consistent the dance! Events
  • 11. What’s that dance you’re doing? denormalizer dbdenormalizer dbdenormalizer db denormalizer svc-3 svc-2 web-uiweb-uisvc-1 the dance! chain reaction of events which play out as a result of an incoming command. each service subscribes to the events they care about choreography! (not orchestration) Events
  • 12. commands tell services when an actor wants an action clients send commands to instruct a service to do work commands are sent asynchronously; fire and forget commands are present-tense, directives: order.create web app order-svc order.create commands are sent directly to a single receiving service
  • 13. events tell the world when you’re done services publish to inform other services of work / actions performed, and state updated services publish (broadcast) events to any services that wish to subscribe events past-tense, describe what happened: order.created order-svc fulfillment-svc order.createdorder.created order.created order.created
  • 14. Two types of services denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 front end
  • 17. web-uiweb-uiweb-app web client web-uiweb-uisvc front end (an app’s perspective) denormalizer dbdenormalizer dbdenormalizer db What’s different? Apps (and apis) still query a db to get the state of the system Never directly modify the db they read from Let’s focus on:
  • 18. web-uiweb-uiweb-app web client web-uiweb-uisvc denormalizer dbdenormalizer dbdenormalizer db What’s different? Instead, apps (and apis) send commands instructing services to perform an action Apps expect their read only representation of system state will eventually be updated in the denormalizer db Let’s focus on: front end (an app’s perspective) Commands are sent over a reliable transport (rabbitmq, kafka, zeromq, etc) to ensure delivery and eventual consistency
  • 19. Let’s pick a transport!
  • 20. rabbitmq messaging that just works • direct send to queue • fanout / topic routing • highly available • highly performant • used in financial exchanges, industrial applications and more • open source • free
  • 21. rabbitmq messaging that just works brew install rabbitmq
  • 23. servicebus super simple messaging in node • direct send • pub / sub / fanout / topic -routing • simple to set up • highly performant • used in financial exchanges, online advertising and more • open source • free • perfect for creating microservices!
  • 24. servicebus super simple messaging in node npm install servicebus —save
  • 27. Sending commands from the front end // web-app, onButtonClick. instead of updating db. const bus = require('servicebus').bus(); bus.send(‘order.create', { 
 order: { userId: userId, orderItems: items } }); web-uiweb-uiweb-app web-ui web-uisvc // fire and forget. command name command itself order.create command
  • 28. Then what from the front end? web-uiweb-uiweb-app denormalizer dbdenormalizer dbdenormalizer db We wait. • reactive / realtime: • mongo oplog tailing (meteor) • rethinkdb • redis notifications • couchdb • graphQL • polling • non-realtime: • product design: thanks! we’re processing your order! check back later for updates! queries!
  • 29. We wait. For the backend. Choreography. It’s eventually consistent!
  • 33. back end (a service’s perspective) web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state Let’s focus on:
  • 34. Sample service. web-uiweb-uiweb-app web-ui web-uisvc command name command object // order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); service publishes to the world when it’s done! order.create command order.created event
  • 35. Sample service. web-uiweb-uiweb-app web-ui web-uisvc listening for commands performing business logic & updating state// order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); order.create command order.created event completing atomic transaction and allowing error handling
  • 36. back end (a downstream service’s perspective) web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state svc-2 Events Events Let’s focus on: Same thing!
  • 37. Sample downstream service. web-uiweb-uiweb-app web-ui web-uisvc // fulfillment-svc index.js const bus = require(‘./bus’); const fulfill = require(‘./lib/fulfill’); bus.subscribe(‘order.created', (event) => { fulfill(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.fulfilled’, order, () => { event.handle.ack(); }); }); }); order.created order.fulfilled subscribe for events instead of listening for commands no different, from any other service!
  • 39. servicebus-register-handlers convention based event handler definition for distributed services using servicebus. automatically registers event & command handlers saved as modules in folder initialize at startup
  • 40. servicebus-register-handlers const bus = require(‘./lib/bus'); // instantiate servicebus instance const config = require('cconfig')(); const log = require('llog'); const registerHandlers = require('servicebus-register-handlers'); registerHandlers({ bus: bus, handleError: function handleError (msg, err) { log.error('error handling %s: %s. rejecting message w/ cid %s and correlationId %s.', msg.type, err, msg.cid, this.correlationId); log.error(err); msg.handle.reject(function () { throw err; }); }, path: './lib/handlers', queuePrefix: 'my-svc-name' }); initialize at startup: provide initialized bus define your error handling path to your handlers prefix to differentiate similar queues
  • 41. servicebus-register-handlers const log = require("llog"); module.exports.ack = true; module.exports.queueName = 'my-service-name-order'; module.exports.routingKey = "order.create"; module.exports.listen = function (event, cb) { log.info(`handling listened event of type ${event.type} with routingKey $ {this.routingKey}`); /* do something with your event */ cb(); }; each handler is a file no params marks success. pass back error to retry or fail. callback based transactions! differentiate queues for different services specify which commands or events to listen or subscribe to
  • 42. servicebus-register-handlers super simple messaging in node npm install servicebus-register-handlers —save
  • 43. What about the ‘work’ part? const log = require("llog"); module.exports.ack = true; module.exports.queueName = 'my-service-name-order'; module.exports.routingKey = "order.create"; module.exports.listen = function (event, cb) { log.info(`handling listened event of type ${event.type} with routingKey ${this.routingKey}`); /* do something with your event */ cb(); }; // order-svc index.js const bus = require(‘./bus’); const create = require(‘./lib/create’); bus.listen(‘order.create', (event) => { create(event, (err, order) => { if (err) return event.handle.reject(); bus.publish(‘order.created’, order, () => { event.handle.ack(); }); }); }); these parts
  • 44. What about the ‘work’ part? That’s up to you! Need an audit trail? Targeting finance? Consider event sourcing. *and my framework, ‘sourced’ Depending on your problem, the right choice could be mongoose and mongodb, a graph database, an in-memory data structure, or even flat files. CQRS makes no assertions about what technology you should use, and in fact frees you to make a different decision for each particular problem. and depends on the problem you’re solving
  • 45. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; bus.use() middleware into bus message pipeline. middleware can act on incoming and/or outgoing messages
  • 46. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; packages outgoing message data and adds useful type, timestamp, and other properties
  • 47. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; adds a correlationId for tracing related commands and events through your system
  • 48. But wait! There’s more! servicebus middleware! middleware can inspect and modify incoming and outgoing messages // ./lib/bus.js required as single bus instance used anywhere in service const config = require('cconfig')(); const servicebus = require('servicebus'); const retry = require('servicebus-retry'); const bus = servicebus.bus({ url: config.RABBITMQ_URL }); bus.use(bus.package()); bus.use(bus.correlate()); bus.use(retry({ store: new retry.RedisStore({ host: config.REDIS.HOST, port: config.REDIS.PORT }) })); module.exports = bus; now, every failed message will retry 3 times if errors occur. after that, the message will automatically be put on an error queue for human inspection!
  • 49. And more! distributed tracing middleware! var trace = require('servicebus-trace'); bus.use(trace({ serviceName: 'my-service-name', store: new trace.RedisStore({ host: config.REDIS_HOST || 'localhost', port: config.REDIS_PORT || 6379 }) }));
  • 51. back end services web-uiweb-uiweb-app svc Commands Events• Listen for commands and subscribe to events • Performs business logic to process commands and events • Update local state (optionally) • Publish events to tell external services of updated state Recapping:
  • 54. back end What’s a denormalizer? front end • Just another back end service • Has one job to do • Subscribe to all events that the UI cares about • Persist events in a format most efficient for the UI to view • Completes the eventually consistent, unidirectional flow denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web client denormalizer Events svc
  • 56. Recapping the big picture. denormalizer dbdenormalizer dbdenormalizer db web-uiweb-uiweb-app web-uiweb-uiweb-api web client mobile client denormalizer svc-3 svc-2 web-uiweb-uisvc-1 Queries Commands unidirectional flow eventually consistent the dance! Events
  • 58. Thanks! We’ll sneak preview even more tooling for easily building these systems in a future talk!
  • 59. Matt Walters github & twitter: @mateodelnorte email: hi@iammattwalters.com website: iammattwalters.com rabbitmq.com npmjs.com/package/servicebus How to CQRS in Node npmjs.com/package/servicebus-register-handlers npmjs.com/package/servicebus-retry npmjs.com/package/servicebus-trace