What is an event-driven architecture, what can it do for your architecture, and is it a prerequisite for microservices?
In this talk, we'll see what events are and how they can solve many of the coupling and integration problems that you will experience in a distributed (micro)service landscape.
We'll get into the different usages for events and showcase them based on real world projects.
After this talk, you will know what events are, how they can be used and some of the requirements they put on your design and the way you thinking about software design.
7. @jeppec
Synchronous Request/Response
lowers our tolerance for faults
• When you get an IO error
• When servers crash or restarts
• When databases are down
• When deadlocks occurs in our databases
• Do you retry?
With synchronous Request/Response we can loose business data if there’s no automatic retry mechanism.
Also if the operation we retry isn’t idempotent* we risk having the side effect multiple times!
Client Server
Processing
The same message can be
processed more than once
*Idempotence describes the quality of an operation
in which result and state does not change if the
operation is performed more than 1 time
Request
Processing
Duplicated Request
Duplicated Response
Response
16. @jeppec
What’s wrong with distributed transactions?
• Transactions lock resources while active
• Services are autonomous
• Can’t be expected to finish within a certain time interval
• Locking keeps other transactions from completing their job
• Locking doesn’t scale
• X Phase Commit is fragile by design
17. @jeppec
Learnings
• Task/Activity services needs to perform UPDATES across multiple
data/entity services. Requires distributed transactions or fully
asynchronous process management.
• The more synchronous request-response remote calls you have to
make the more it hurts Performance and latency.
• Robustness is lower. If one data/entity services is down it can take
down many other services.
• Coupling is higher. Multiple task/activity services manage the same
CRUD data/entity services
• Cohesion is likely lower as multiple task/activity services need to
replicate entity related logic
24. @jeppec
Accidental complexity from distributed service integration
Warehouse
Service
Order
Service
Billing
Service
UI
Send- Invoice Save-Order
Reserve-
Items
Local transaction between 2 local
“Services”
Remote call
26. @jeppec
Dual write problem
Order
Service
Billing
Service
Client
Send- Invoice
Save-Order
Remote call
causing a side
effect
Expected transaction
boundary
No simple solution (except a classic monolith)
• Local-commit-then-publish
• If the app crashes after local-
commit then the publish
operation isn’t performed
• Publish-then-local-commit
• If the local-commit fails then
we’ve already formed the publish
operation
• Billing Service may receive
published message BEFORE the
Order Service has committed
its transaction
27. @jeppec
Order:Save-Order()
call Warehouse:Reserve-Items()
call Billing:Send-Invoice()
if (Billing:Call-Failed:Too-Busy?)
Wait-A-While()
call Billing:Send-Invoice()
if (Billing:Call-Failed:Too-Busy?)
Wait-A-Little-While-Longer()
call Billing:Send-Invoice()
if (Billing:Call-Failed:IO-Error?)
Save-We-Need-Check-If-Call-Billing-Succeded-After-All
AND We-Need-To-Retry call Order:Save-Order and call Warehouse:Reserve-Items
AND Tell-Customer-That-This-Operation-Perhaps-Went-Well
if (Billing:Call-Went-Well?)
commit()
Accidental complexity from distributed service integration
Warehouse
Service
Order
Service
Billing
Service
UI
Send- Invoice Save-Order
Reserve-
Items
Local transaction between 2
Components
28. @jeppec
“A distributed system is one
where a machine I’ve never heard
of can cause my program to fail”
— Leslie Lamport
31. @jeppec
Solution
Model our data and usecases, so that all our overall usecase can be
turned into a set of indepent transactions that are asynchronously
chained.
Accept
Order
?
Receive
Payment
?
Ship
Order
This means that our business data must be collected in Entities,
that should be limited in size (but not smaller),
so that, after a transaction they are consistent
(Pat Helland – Life Beyond Distributed Transactions)
33. @jeppec
Synchronous calls are the crystal meth of programming
At first you make good progress but then the sheer horror
becomes evident when you realise the scalability limitations
and how the brittleness holds back both performance and
development flexibility. By then it is too late to save.
http://www.infoq.com/news/2014/10/thompson-reactive-manifesto-2
We need the reactive properties and then apply protocols
for the message interactions. Without considering the
protocols of interaction this world of micro-services will
become a coordination nightmare.
Martin Thompson
34. @jeppec
Coupling matrix*
* Modified version of Ian Robinson’s matrix: http://iansrobinson.com/2009/04/27/temporal-and-behavioural-coupling/
Behavioral
coupling
Temporal
coupling
Low High
Low
High
Reactive/
Event oriented
Command oriented
Emergency services Distributed 3 layer
35. @jeppec
Events
An Event is non-prescriptive of what should happen in other parts of the system.
An event will typically be published to multiple consumers/subscribers:
• The publisher of the event does not know who the subscribers are
• And the publisher doesn’t know what the subscribers intend to do with the event
Events always carry a name in its past-tense form:
OrderWasAccepted
OrderHasShipped
CustomerWasReimbursed
“An Event describes a FACT, i.e., something that HAS happened”
36. @jeppec
Different uses for Events
• Master data management and Data duplication
• Data replication / migration
• Notification
• UI component integration
• Service autonomy and Loosely coupled workflows/business processes
across Services
37. @jeppec
This means we must switch from
a
Request/Response (pull)
to a
Reactive (push) model
A change with profound consequences
40. @jeppec
We need to shift focus from pure data
towards intent and process automation
This means a change from CRUD style application design, where the
process was implicit and stored in the minds of the users
First I need to
enter the
employee in
this screen
Then I need to press
a button in the user
system so they’re
properly created
And the I need to
add their access
card to this screen
and press Activate
41. @jeppec
Task-based/Inductive UI
• Traditional CRUD UI is what I would call a WHAT UI
• Task based UI’s focuses on HOW the user wants to use the
application
• Guides users through the work process
• The UI becomes an intrinsic part of the design
• The UI design directly affects our commands and thereby our
transactional boundaries
42. @jeppec
We need to capture User Intent at the UI
CRUD style
Task based style
Intent
43. @jeppec
Capturing intent in the form of a Command
A Command is prescriptive of what should happen, and its primary goal is to capture USER
INTENT
A Command
supports a single usecase and
targets a single business object
within a single Transaction
Commands always carry a name in its imperative form:
• AcceptOrder
• ShipOrder
• CancelOrder
• ReimburseCustomer
• Etc.
“A command describes a Task that you want someone else to carry out
for you and where the recipient can choose to reject the Command”
44. @jeppec
Commands & Events symmetry
• Commands change Business Object (Entity) state which results in one
or more Events being published.
Command Event(s)
AcceptOrder OrderAccepted
ShipOrder OrderShipped
AddComment CommentAdded
QuarantineReview ReviewQuarantined
UnquarantineReview ReviewUnquarantined
Command Event
45. @jeppec
Command to Event
public class OrderService {
public void handle(AcceptOrder cmd) {
orderRepository.add(new Order(cmd.orderId,
cmd.orderLines));
eventBus.publish(new OrderAccepted(cmd.orderId,
cmd.orderLines));
}
46. @jeppec
Unambigous commands?
Order Id?
•Is it ISO-4217 3 characters
currency code (such
as USD and DKK)?
•Is it ISO-4217 Currency numbers
(such as 840 and 208)?
•Is it the currency name (such as US
Dollar and Danish Krone)?
•Is it the sales tax as
a Percentage ?
•Is it the calculated sales
tax as an Amount ?
•Is
the key the ProductId ?
•Is the value a Quantity ?
AcceptOrder
48. @jeppec
Using Business Events to drive Business Processes
Sales Service
Shipping
Billing
Sales
Customers
Message
Channel
Online Ordering System
Web Shop
(Composite UI)
Billing Service
Warehouse Service
<<External>>
Order Paid
MarkOrderAsPai
d
The sales
fulfillment
processing can
now begin…
Cmd Handler
Order Paid
Apply
50. @jeppec
We need to change focus from short
technical transactions
To long running business transactions supporting
business processes
51. @jeppec
Choreographed Event Driven Processes
Sales Service
Order Paid
Billing Service
Shipping Service
Warehouse Service
Online Ordering System
Message
Channel
(e.g.
a
Topic)
Order Paid
Customer
Invoiced
Order Paid
Items
Reserved
Order Paid
Shipping process
works as a Finite
State Machine
(WorkFlow)
handling the life
cycle of Shipping and
thereby forms a very
central new
Aggregate in the
System
Items
Reserved
52. @jeppec
Eventual consistency
• Consistency is with each Service
• Eventual consistency is between Services
• Like in the real world
Sales Invoicing
Inventory Shipping
Order
Accepted
Invoice Customer
Checks Inventory for availability Books truck driver
Order
Packaged
Fetch Package from Inventory
Customer
Invoiced
54. @jeppec
Equally important!
Focus on identifying IF you’re within the
happy path of the process
From a ROI perspective many edge cases
are better handled by humans than trying
to automate them
56. @jeppec
Reactive/Push model
• Event based integration follows a push-based model that breaks
temporal coupling and avoids cascading failures
• Events can be exchanged between services over a message channel,
that can be implemented using a push or pull protocol
Publisher
Subscriber
Asynchronous Communication – A.k.a. Messaging
Customer Moved
Customer Moved
Subscriber
Customer Moved
Channel
57. @jeppec
Smart pipes and “dumb” endpoints – (Push protocol)
Service X
Publisher
Data and flow direction
Message infrastructure
(e.g. Kafka, RabbitMQ, …)
Service Z
Subscriber
Service Y
Subscriber
Service M
Subscriber
Topic
58. @jeppec
Service X
Publisher
Service Z
Consumer
Service Y
Consumer
Service M
Consumer
Atom File based Feed
generator
Oldest
Feed
Older
Feed
Old
Feed
Feed
Head Previous feed link
HTTP
Endpoint
Next feed link
Next feed link
Previous feed link
HTTP Reverse
Proxy
HTTP Reverse
Proxy
Cache
Cache
Atom Pub Feed
as a JSON/XML
file
Dumb pipes and smart endpoints (Pull Protocol)
Data and flow direction
59. @jeppec
Topic features
• Decouples publisher from subscribers
• Provides temporal decoupling
• If a subscriber is unavailable, it will receive its messages when it comes
online
Topics
Service - 4
Service - 1
Service - 3
61. @jeppec
There’s just one issue
public class OrderService {
public void handle(AcceptOrder cmd) {
orderRepository.add(new Order(cmd.orderId,
cmd.orderLines));
eventBus.publish(new OrderAccepted(cmd.orderId,
cmd.orderLines));
}
Dual Write problem still
exists!
63. @jeppec
Dual write problem
using Event Sourcing
Order
Service
Billing
Service
Client
Send- Invoice
Save-Order
Transaction
boundary
Transaction
boundary
Event Store
• Requires only local transactions
• Natively event driven: The Service
consumes and produces events
• Proven Audit Trail
• Flexible and adaptable
• Captures business intentions as events
• Requires idempotent operations
65. @jeppec
Typed Events
public class OrderAdded extends Event<OrderId> {
public final CustomerId orderingCustomerId;
public final long orderNumber;
public OrderAdded(OrderId orderId, CustomerId orderingCustomerId, long orderNumber) {
aggregateId(orderId);
this.orderingCustomerId = orderingCustomerId;
this.orderNumber = orderNumber;
}
}
public class ProductAddedToOrder extends Event<OrderId> {
public final ProductId productId;
public final int quantity;
public ProductAddedToOrder(ProductId productId, int quantity) {
aggregateId(orderId);
this.productId = productId;
this.quantity = quantity;
}
}
66. CRUD
There’s no reason to delete data or update data.
We only need to append and read Events from our Event Store
67. @jeppec
Full CQRS with EventSourcing
UI Domain
Event
Store
Commands – Change data
Commands Events
UI Data
Queries – Ask for data
Events
Query Build
Our single source
of truth
SQL DB Graph DB
Document DB
68. @jeppec
Typed Aggregate
public class Order extends AggregateRoot<OrderId, Order> {
private Map<ProductId, Integer> productAndQuantity;
private boolean accepted;
public Order(OrderId orderId,
CustomerId orderingCustomerId,
int orderNumber) {
FailFast.requireNonNull(orderId, "You must provide a orderId");
FailFast.requireNonNull(orderingCustomerId, "You must provide an
orderingCustomerId");
apply(new OrderAdded(orderId,
orderingCustomerId,
orderNumber));
}
public void addProduct(ProductId productId, int quantity) {
FailFast.requireNonNull(productId, "You must provide a productId");
if (accepted) {
throw new IllegalStateException("Order is already accepted");
}
apply(new ProductAddedToOrder(productId, quantity));
}
69. @jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Sequence
Number
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Accepted: true
Orderline
Orderline
70. @jeppec
Aggregate replay
public class Order extends AggregateRoot<OrderId, Order> {
private Map<ProductId, Integer> productAndQuantity;
private boolean accepted;
public void accept() {
if (accepted) {
return;
}
apply(new OrderAccepted());
}
@Override
protected void applyEventToTheAggregate(Event<OrderId> event) {
if (event instanceof OrderAdded e) {
productAndQuantity = HashMap.empty();
} else if (event instanceof ProductAddedToOrder e) {
Option<Integer> existingQuantity = productAndQuantity.get(e.productId);
productAndQuantity = productAndQuantity.put(e.productId, e.quantity + existingQuantity.getOrElse(0));
} else if (event instanceof ProductOrderQuantityAdjusted e) {
productAndQuantity = productAndQuantity.put(e.productId, e.newQuantity);
} else if (event instanceof ProductRemovedFromOrder e) {
productAndQuantity = productAndQuantity.remove(e.productId);
} else if (event instanceof OrderAccepted) {
accepted = true;
}
}
71. @jeppec
Topic features
But how do we handle:
• Coding errors in Subscribers?
• New Subscribers that didn’t exist when the events were originally
published?
Topics
Service - 4
Service - 1
Service - 3
72. @jeppec
Client handled subscriptions
• Highly resilient pattern for an Event Driven Architecture that’s backed by
Event-Sourced services
• In this model the publisher of the Events is responsible for the durability of
all its Events, typically to an EventStore/EventLog.
• Each client (subscriber) maintains durable information of the last event it has
received from each publisher.
• When ever the client starts up it makes a subscription to the publisher
where it states from which point in time it wants events published/streamed
to it.
• This effectively means that publisher can remain simple and the client
(subscriber) can remain simple and we don’t need additional sophisticated
broker infrastructure such as Kafka+ZooKeeper.
73. @jeppec
Client handled subscriptions
RSocketEvent
StreamSubscription
Local storage
EventStore
RSocketEvent
StreamSubscription
Local storage
EventStreamSubscription
Message
EventStreamSubscription
Message
EventStoreEventStreamPublisher
EventStoreEventStreamPublisher
Event
Event
Event Event
Supports
Single Instance
Subscriber, which
ensures that only
one instance of
Subscriber B has
an active
subscription.
Other instances of
the same
subscriber are
hot-standby
<<Topic Subscriber>>
Customer_Service:Some_Ac:OrderEvents
<<Topic Publisher>>
Sales_Service:OrderEvents
RSocketServer
tcp://subscribe-event-stream
A
B
Subscriber B
RSocket Request/Stream
Event-Stream
Subscriber A
RSocket Request/Stream
Event-Stream Flux<PersistedEvent> eventStream(long fromInclusiveGlobalOrd
Option<String> subscripti
81. @jeppec
Event coordination
• Do NOT copy data from incoming event to outgoing event – instead use
Event coordination from the next slide
Service C Event C
Data:
X
Data: Y
Data:
C, Y
Service D
This form of data copying from incoming
event to outgoing event is prohibited
82. @jeppec
Event coordination continued
• Rule: If Service D also needs data from Event B, then Service D should
also listen for Event B instead of having Service C copy data from Event
B to Event C
Service C Event C
Data:
X
Data: Y
Data:
C
Service
D
Data: Y
83. @jeppec
Avoid using Events for generic services
When ever a new Service is introduced
the Generic Service (X) needs to be changed.
This creates an unnecessary degree of coupling
Service
A
Service
B
Service
C
Service X
Service
D
Event X
84. @jeppec
Use Commands for generic services
Instead of having Service X listen for MANY different events, let
Service X expose a command interface that other services can
use instead
Service
A
Service
B
Service
C
Service X
Service
D
Event X
85. @jeppec
There are only two hard
problems in distributed
systems
2. Exactly Once Delivery
1. Guaranteed Order of Messages
2. Exactly Once Delivery
@mathiasverraes
86. @jeppec
Things are not quite the same
In a distributed system the order in which messages arrive is not
guaranteed
In a distributed systems message delivery can and will fail!
Messages can be delivered according to these guarantees:
• At Most Once – If you don’t care about loosing messages
• Page visits
• Ad views
• Exactly Once
• Not really possible
• At Least Once
• For everything else – which is why:
Everything that can handle messages must be built with idempotency in mind!
87. @jeppec
Message Handling
public class OrderShippingProcess extends MessageHandler {
@MessageHandler
private void on(OrderPaid orderPaid, ItemsReserved itemsReserved) {
ShippingDetails shippingDetails = getShippingDetailsForOrder(orderPaid.orderId);
….
printShippingLabel(orderPaid.orderId, shippingDetails.address);
}
…
} Must also be idempotent
88. @jeppec
Event Monitoring
• One of the challenges with have Event based systems is to keep track
of where events are in the flow
• Why isn’t this system doing this?
• Did events go into an Error Queue?
• How can we reprocess them?
• Or why isn’t this happening?
• In general, it’s the same issues we see with asynchronous systems and
integrations in general.
• The good thing about using Events is that they carry semantics and are not RPC
in hiding
89. @jeppec
Event Monitoring
Command, Document and Event messages all contain the following data:
• Timestamp
• Unique message Id
• Correlation Id
• Caused by Event Id
• Originating system (IP address, name, etc.)
• …
Event messages also need to describe the order in which the event occurred.
This can be implemented in many ways including:
• Ordering sequence number
• Event vectors
• Vector clocks
• Timestamp
• Etc.
91. @jeppec
When to prefer a Request/Response (Pull) based
model?
• You want to have Authority (as opposed to Autonomy)
• Such as with a bank account
• GDPR compliance
• So sensitive data is only stored in one place (avoid data duplication)
• Orchestration of processes
• Sometimes event choreography can result in too much ceremony
• You have large amounts of data and your queries only involve a small set of
this data
• Example a Google search
• Most UI to backend interactions
• Loading data from the backend
• Pressing a button to send a Query or issue a Command (e.g. Accept Order)
93. @jeppec
"I consider 'getting the boundaries
right' the single design decision with
the most significant impact over the
entire life of a software project."
@ziobrando
99. @jeppec
If we primarily model around nouns/entities we can
easily violate the SRP
Where a change to requirements
is likely to require changes
to multiple entity classes
112. @jeppec
If we align the problem domain with the solution domain
Bounded Context 1 Bounded Context 3
Bounded Context 2
UI
BL
DAO
UI
BL
DAO
UI
BL
DAO
Vertical coupling
is
unavoidable
We want to avoid
horizontal coupling
114. @jeppec
A Service is
• The technical authority for a given bounded context
• It is the owner of all the data and business rules that support this
bounded context – everywhere
• It forms a single source of truth for that bounded context
http://udidahan.com/2010/11/15/the-known-unknowns-of-soa/
115. @jeppec
Be aware of Conways Law
“organizations which design systems ... are constrained to produce
designs which are copies of the communication structures of these
organizations”
Teams are typically aligned with Systems
and NOT with Services as they should
Said another way: How you organize yourself, determines your architecture
116. @jeppec
Business Capability alignment
“The advantage of business capabilities is their remarkable level of
stability. If we take a typical insurance organisation, it will likely
have sales, marketing, policy administration, claims management,
risk assessment, billing, payments, customer service, human
resource management, rate management, document
management, channel management, commissions management,
compliance, IT support and human task management capabilities.
In fact, any insurance organisation will very likely have many of
these capabilities.”
See http://bill-poole.blogspot.dk/2008/07/business-capabilities.html
117. @jeppec
Business – IT alignment
• We want the Business and IT to speak the same Ubiquitous language
• Want want our architecture to be aligned with the business capabilities
• Because these capabilities are stable
118. @jeppec
Many perspectives on data
Online Retail System
Product
Unit Price
Promotional Price
Promotion End Date
Stock Keeping Unit (SKU)
Quantity On Hand (QOH)
Location Code
Price
Quantity Ordered
Name
The lifecycle of the data is VERY important!
Customer
Pricing
Inventory
Sales
Management Reporting
119. @jeppec
Smaller models & clear data ownership
Retail System
Pricing
Product
ProductID
Unit Price
Promotional Price
…
Pricing
Inventory
Product
ProductID
SKU
QOH
Location Code
…
Inventory
Sales
Product
ProductID
Name
Description
Quantity Ordered
…
Sales
Shared Entity identity
DDD:
Bounded
Context
Business
Capability Service
120. @jeppec
Bounded Contexts and Aggregates
Sales
Product
Customer
customerId
…
Order
orderId
customerId
…
OrderLine
orderId
productId
quantity
timestamp
priceId
ProductCategory
productCategoryId
…
Pricing
Product
productId
productCategoryId
name
tag
...
Product-Price
priceId
productId
normalPrice
discountPeriods
…
121. @jeppec
Using Business Events to drive Business Processes
Sales Service
Shipping
Billing
Sales
Customers
Message
Channel
Online Ordering System
Web Shop
(Composite UI)
Billing Service
Shipping Service
<<External>>
Order Accepted
AcceptOrder
The sales
fulfillment
processing can
now begin…
Cmd Handler
Order Accepted
Apply
127. @jeppec
Service and deployment
• A Service represents a logical responsibility boundary
• Logical responsibility and physical deployment of a Service
DOES NOT have to be 1-to-1
• It’s too constraining
• We need more degrees of freedom
• Philippe Krutchen 4+1 views of architecture: Logical and Physical
designs should be independent of each other
A service needs to be deployed everywhere its data is needed
130. @jeppec
Service Microservices
1..*
Is implemented by
Service vs Microservices
Microservices are a division of Services along Transactional boundaries (a transaction stays within the
boundary of a Microservice)
Microservices are the individual deployable units of a Service with their own Endpoints. Could e.g. be the
split between Read and Write models (CQRS) - each would be their own Microservices
131. @jeppec
A Service represents a logical boundary
131
Service
Microservice
Microservice Microservice
Microservice
132. @jeppec
Services are the corner stone
• We talk in terms of Services capabilities and the processes/use-cases
they support
• Microservices are an implementation detail
• They are much less stable (which is a good thing – it means they’re easier to
replace)
133. @jeppec
Service deployment
• Many services can be deployed to the same physical server
• Many services can be deployed in the same application
• Application boundary is a Process boundary which is a physical boundary
• A Service is a logical boundary
• Service deployment is not restricted to tiers either
• Part of service A and B can be deployed to the Web tier
• Another part of Service A and B can be deployed to the backend/app-service tier of the same
application
• The same service can be deployed to multiple tiers / multiple applications
• ie. applications and services are not the same and does not share the same boundaries
• Multiple services can be “deployed” to the same UI page (service mashup)
134. @jeppec
What about Security
Is Security a Service?
• If it’s technical YES
• Example: Authentication & Authorization
• If it’s a business related, i.e. Business rule, – NO
• Then it belongs inside the Service responsible for this business capability
• Example: Who’s allowed to authorize large transfers or who’s allowed to
reimburse the customer
135. @jeppec
How do we bring things together for our users
without introducing unnecessary coupling?
138. @jeppec
iOS Home banking
Customer information
Legal and contract information
Accounts
Credit card
Mortgage loans
Web banking portal
Bank Back-office application
139. @jeppec
Let’s assume we have these services
Currency
Service
Customer
Service
Identity
Management
Service
Sales
Service
Inventory
Service
Products
Service
IT Operations
Shipping
Service
Web Shop
140. @jeppec
Back-end for Front-end?
Client
Remote Facade
DTOs
Identity
Management
Service
Customer
Service
Products
Service
Sales
Service
Inventory
Service
Shipping
Service
Currency
Service
IT Operations
141. @jeppec
Service A Service B Service C
IT-OPS
Web shop
Warehouse
Back office
App logic
(Layered, CQRS,…)
Warehouse
Storage
UI Components
A Services owns its UI Components
148. @jeppec
Service Widget Service Widget
Page
Service Widget
Service Widget
Service Widget
• Overall structure of the page
is “owned” by the application.
• Each service widget is independent
Composite page layout
Service Widget Service Widget Service Widget
Service Widget
149. @jeppec
https://our.micro-cool.bank-portal
Customer
Name: Peter Hansen
Address: Some Road 1
Some Zip Some City
Customer relations
Spouse: Mette Hansen
Children: Jacob Hansen
Ditte Hansen
Overview Page
(owned by the
application)
<<UI Component>>
Customer Details Component
<<UI Component>>
Customer Relations
Component
UI layer
Backend layer
Customer Details
Microservice
Customer Relations
Microservice
HTTPS HTTPS