Microservices — micro-what?

Thomas Woo
7 min readAug 25, 2021

What is a microservice?

First, let’s take a step back. Do we know what an app is?

I think we all pretty much have a good idea of what an app is. And that is precisely what a microservice is. A microservice is just an app. But it’s not just any app — it’s a special type of app.

All microservices are apps, but not all apps are microservices.

So what separates a microservice from any other app?

It comes down to responsibility. In short, a microservice is an app that is responsible for one thing, and one thing only.

Engineers who are familiar with Robert C. Martin’s SOLID principles will have a firm grasp of what constitutes a responsibility. But for others who aren’t as sure, let’s use an example.

There is a microservice that converts CSV files into Excel files. The microservice’s only responsibility is to convert the files. But where do these CSV files come from? That is a separate responsibility. A different microservice will be responsible for getting the CSV file. Regardless of how the CSV files are retrieved, the service that does the converting does not care how it gets the files. It only cares about converting the files and nothing else, that is its only single responsibility.

Ok, single responsibility, I get it… I think.

Sometimes it becomes a little gray on what makes a responsibility be single. Although there are tons of esoteric definitions of single responsibility, it is still one of the hottest debates among engineers.

Going back to the example above. Let’s think of about what a conversion is. Is it just the change in binary sequences from a comma-separated-value text file to a Microsoft spreadsheet file? What about formatting? What happens if we want to also do more than just make a file readable in Excel, such as make the headings bold and add pretty colors? Is that a new responsibility?

It depends.

If the CSV files are homogeneous, then yes, treating conversion and formatting as one responsibility might be acceptable — sometimes preferable.

However, what if the CSV files are not homogeneous? What if depending on the name of the file, we’ll either make the font bright red, or dark blue. Or maybe we want to bold certain words. Then it’s probably a good idea to treat it as a separate responsibility.

Separating responsibilities is 95% science, and 5% art. Unfortunately, that last 5% is the hardest part. This is also where an experienced engineer becomes pivotal in software development.

So to sum up, microservices are apps with one responsibility, or at least one responsibility within a context.

Since microservices have such limited scopes, each individual service isn’t very useful for users. However, if we take a whole bunch of these “micro apps”, and have them communicate with one another, we can form a network of services that can provide meaningful functionality.

What do we call this network of microservices that work together to form a cohesive system?

An app. That’s right. All these micro apps work together to form… an app.

Microservice Architecture

This is what we refer to as the Microservice Architecture. Prior to microservices, software (especially Enterprise Software) were generally written in a Monolithic Architecture. Unlike microservices, with its many single responsibility apps, a monolith application is just one app that encompasses many responsibilities. Single responsibility and decoupling still play a major role in developing monolith applications, but it’s done at a lower level of the software development — at the code-level.

Wait, then why is it called Microservice instead of Microapplication?

Good question. The answer to that question is something software engineers refer to as state. When software engineers talk about state, they are talking about a memory state. An application’s state is the condition of all variables that is currently assigned within an application.

For example, most calculator apps “remember” prior answers. When you enter 2+2= into a calculator app, it will compute 4. When you follow up by entering +10=, the calculator will compute 14 (your prior answer +10). When you follow up again with the same +10=, it will now compute 24. So even though the input was the same (+10=), the output had changed. This is what we mean by state.

A service is stateless — it shall not have a state. A service’s output will always be the same, as long as the input does not change.

Databases are not considered services because they hold a state. State is actually why databases exist. They allow state to be stored and retrieved.

One might think of services being similar to pure functions. Pure functions are functions that will always return the same output, given the same inputs. The random() function would not be considered pure.

However, unlike pure functions, the “input” for a service does not always have to come in the form of a parameter. Think about a service that gets data from a database. When data is retrieved through the service, the output may change because the data in the database has changed. This is still considered stateless. The state of the data does not belong to the service, it belongs to the database. The database is actually an “input” to the service.

All microservices are services, but not all services are microservices.
Simply put, a microservice is both a service and an app.

Let’s take a look at a Microservice Application.

The diagram below shows several microservices that will allow a user to create a new sale in the system.

The user will only interact with a UI, represented by a package .

Package

Each component in the diagram represents a single microservice.

Component

Databases are for persistence of data — store and retrieve.

Database

Arrows are pointing at the flow of information for creating a new sale.

All the provider services on the left (Agents Provider, Customers Provider, etc.) are responsible for persisting and retrieving data to and from a database.
For example, Customers Provider service is the “gateway” for all other services/applications that need to create a new customer, read an existing customer, update an existing customer, and delete a customer. In short, it is a CRUD (create, read, update, delete) application. It’s a *single point of entry for all customer information.

Agents Service doesn’t do much on its own in this specific scenario (creating new sales). It just passes along Agents data. It is a service layer that sits between the Agents Provider and UI (and other services). However, if some behavior was needed for Agents data, such as creating new sales agents, this is where its business logic lives. Generally, it’s good practice to have a service layer sitting between the data layer and the user interface layer.

Customers Service ditto — see above :)

Product Inventory Service aggregates information about a product and its inventory. What is the product? Is the product in stock? If so, how many? etc.

Sales Service creates new sales by gathering order details from the user (information entered through the UI), retrieving information from other services, and then creating a new sales record.
After the sales record is created, it passes the record to the Sales Provider — who will then persist the data to the database.

All these (micro)services work together to provide a meaningful service to the user.

*You may be curious to know why we should only have a single point of entry. This is a very important concept known as decoupling. If we did not have a single point of entry for customer information and every other service/application directly communicated with the database, there would be multiple breaking points.
For example, one day you may need to switch to a new state of the art database that will greatly improve the performance of your application. Unfortunately, your predecessors did not provide a single point of entry to the database, and every service that needs customer information talks directly to the customers database. In this scenario, all these services are
coupled to the database. To switch databases, you will now need to refactor the code for every single one of these services.
This is actually a very far-reaching issue that goes beyond development. QA/Testing will need to test every updated service. Production will need to bring down every updated service in order to make a release.
Very far reaching indeed — please decouple your services!

So what’s the big deal, why all the hoorah?

I’ll let Amazon handle this question :)

--

--