Prashanth ‘PB’ Belathur is an Application Modernization Leader in VMware Tanzu Labs (formerly Pivotal), with extensive experience leading modernization, cloud migration and AI/ML engagements in the finance, insurance, banking, logistics, airline, ecommerce, telecom, healthcare, and retail verticals.
Decompose monoliths using business workflows
TL;DR
Can we start decomposing a monolith using its business workflows ?, in a context of limited or non-existent SMEs, outdated requirements, developers with limited monolith experience, and no tests in the codebase.
BACKGROUND
A major pharmacy chain had frequent outages for a business critical application during COVID, which impacted customer retention and revenues.
The monolith supported prescription management, compliance, sales promotions and analytics.
It performed poorly under high prescription volumes and exhibited load-induced fragility.
The Prescription Fulfillment domain had the most negative impact on the monolith performance. Hence, it was chosen as the candidate to kick off the decomposition effort.
This domain contained a set of business workflows, with each workflow comprised of tasks completed in a specific sequence. The monolith executed multiple workflows to complete a business transaction like filling a prescription for a pharmacy customer.
Our mission was to decompose the Prescription Fulfillment domain from the monolith into highly reliable and scalable services. This was done with the context of limited or non-existent SMEs, outdated requirements, developers with limited monolith experience and no tests in the codebase.
TECHNIQUE
The Swift Method is used to decompose the Prescription Fulfillment domain from the monolith.
- A simplified Prescription Fulfillment domain is used to highlight the technique.
1. Event Storm the workflows
In consultation with Product Owners and SMEs, we identified business workflows in the Prescription Fulfillment domain. This exercise included code, UI walkthroughs, and end-user interviews. The SMEs decided on the naming and granularity of tasks/events in the workflows. We prefer granular over fine grained events. The task and event are synonymous in this post.
We event stormed all the business workflows to discover domains, bounded contexts, ubiquitous language, and pain points. This helped Business and Development to have a common understanding of the domain.
The events in a business workflow can belong to different bounded contexts. For example: the prescription ingestion workflow had events that belonged to prescription-ingestion and prescription-safety-review bounded contexts.
2. Discover Bounded Contexts
3. Map Bounded Contexts to Subdomains
4. Notional Architecture using Boris
- The notional architecture is stateless and event-driven to achieve high reliability and scalability.
- We intentionally did not choose 1 bounded context to 1 service candidate mapping due to legal, operational and organizational constraints in the pharmacy chain.
- Service Candidate is mostly a mini-service (a few bounded contexts) OR rarely a microservice (a single bounded context).
- The high throughput requirement for ingesting prescriptions resulted in Prescription Ingester becoming a microservice.
- The prescription-accuracy and safety-review BCs are included in Prescription for legal and operational reasons.
- A solid red line is the event publisher and the dotted red line is the event subscriber.
TAKEAWAYS
Decompose Capability not Code
The decomposition of a monolith using workflows is heavily dependent on the firm’s legal, operational and organizational constraints. Pick a simple impactful business domain for the kickoff and have the SMEs eliminate redundancies in the existing workflows for the chosen domain.
Go Macro first, then Micro
Start with happy path workflows containing granular events, which leads us quickly to the end-to-end view of the domain model.
Migrate in Baby Steps
The notional architecture is evolutionary in nature. As we discover more workflow details in future iterations, the bounded contexts will undergo further decomposition, move to/from subdomains, and evolve into designing the system as it wants to behave.
Don’t be stuck on each bounded context implemented as a microservice. It’s OK to have a mini service for a few related bounded contexts OR to move to microservices only if it’s absolutely necessary.
Implement bounded context capabilities as thin vertical slices.