PC#18 - Microservices Patterns

Coupling vs Cohesion and More...

Hello, this is Saurabh…👋

Welcome to the 74 new subscribers who have joined us since last week.

If you aren’t subscribed yet, join 1500+ curious Software Engineers looking to expand their knowledge by subscribing to this newsletter.

In this edition, I cover the following topics:

🖥 System Design Concept → Microservices Patterns

🧰 Roundup → Most Popular Posts

🍔 Food For Thought → Coupling and Cohesion

So, let’s dive in.

🖥

System Design Concept

Microservices Patterns

Building microservices isn’t easy.

Even in the best of times, you might end up in a mess.

But if you’ve to build microservices for some reason, it’s better to know some patterns that can make your life easy.

Here are 4 must-know patterns for building microservices:

Database Per Service

As the name suggests, this pattern proposes that each microservice manages its own data.

This implies that no other microservice can directly access or manipulate the data managed by another microservice.

Any exchange or manipulation of data can be done only by using a set of well-defined APIs. 

The below figure shows an example of a database-per-service pattern.

At face value, this pattern seems quite simple. You can implement it relatively easily when you are starting a brand-new application.

However, when you are trying to migrate an existing monolithic application to a microservices architecture, the demarcation between services is not so clear.

Most of the functionality is written in a way where different parts of the system access data from other parts informally.

Two main areas that you must focus on when using a database-per-service pattern are:

  • Defining bounded contexts for each service.

  • Managing business transactions spanning multiple microservices.

Shared Database

The next important pattern is the shared database pattern.

Depending on how you are looking at things, this might also sound like an anti-pattern.

That’s because this pattern adopts a much more lenient approach by using a shared database accessible to multiple microservices.

Here’s what it looks like in practice:

For existing applications transitioning to a microservices architecture, this is a much safer pattern as we can slowly evolve the application layer without changing the database design.

However, this approach takes away some key benefits of microservices.

  • Developers across teams need to coordinate schema changes to tables

  • Runtime conflicts may arise when multiple services are trying to access the same database resources.

API Composition

The API Composition pattern attempts to solve the problem of implementing complex queries in a microservices architecture.

An API composer invokes other services in the required order. After fetching the results, it performs an in-memory join of the data before returning it to the caller.

However, this is an inefficient approach due to in-memory joins on potentially large datasets.

Check the below illustration:

CQRS and Event Sourcing

CQRS stands for Command Query Responsibility Segregation.

In the CQRS pattern, an application listens to domain events from other microservices and updates a separate database for supporting queries and views. 

You can then serve complex aggregation queries from this separate database while optimizing the performance and scaling it out as needed.

Event Sourcing takes it a bit further by storing the state of the entity or the aggregate as a sequence of events. 

Whenever there is an update or an insert on an object, a new event is created and stored in the event store. 

You can use CQRS and Event Sourcing together to solve a lot of challenges around event handling and maintaining separate query data. This way, you can scale the read and writes separately based on specific requirements.

On the downside, this is an unfamiliar style of building applications for many developers and there are also multiple moving parts to manage.

Check out the below illustration that shows CQRS and Event Sourcing together.

🧰

Round-Up

The last few weeks have been really busy creating a bunch of articles for all of you amazing subscribers.

Here’s a quick round-up of the best pieces (in case you’ve missed some along the way):

🍔

Food For Thought

👉 Low Coupling and High Cohesion

That’s one thing that most software engineers want in their systems.

It’s also the one thing that seems within reach during development…

…but escapes after you’re done with the project.

Let’s understand them today - once and for all!

Coupling

Coupling is the interdependence between software modules or components.

What does it mean in plain English?

If your system is highly coupled, change in one module leads to changes across the entire system.

You hit one nail in the wall and the entire house collapses around you.

Cohesion

Cohesion is the degree to which the elements within a module or component are related to one another.

Simply put…if your module has high cohesion, it means the elements are closely related and work together to perform a well-defined task.

Think of a team where everyone has each other’s back and supports each other on the field.

So what do you really want in your systems?

Ideally, you want to have Low Coupling and High Cohesion.

👉 Low Coupling results in better flexibility and easier maintenance because you don’t have to know about every relation in the system while making a change.

👉 High Cohesion makes your code more readable and easier to change because everything you need to know is right there in front of you.

Some steps to achieve this:

Think about your application in terms of Bounded Contexts.

Few things I'd try to do from the start:

  • Divide & Conquer. Each module should do a fixed thing.

  • Keep the functionalities separated from each other. Look at Vertical Slice Architecture 

  • Try to go for single ownership of data wherever possible or have clear-cut interfaces.

While you might get quick success identifying boundaries at the technical level, the real benefits show up when you understand these boundaries at the levels of business processes and the underlying domain

👉 Have you seen a job description like this?

Some job descriptions can be downright demoralizing.

Have you ever encountered such a job description?

That’s it for today! ☀️

Enjoyed this issue of the newsletter?

Share with your friends and colleagues

Also, send them over here to subscribe.

In case you want me to cover any specific topic in future editions, please don’t hesitate to fill out the below idea-suggestion form.

See you later with another value-packed edition — Saurabh.

Join the conversation

or to participate.