Purpose-Driven Microservice Design
Tags: webdev, cloud, tutorial, programming
Published: 2022-06-30 11:12:03


![Article Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97m7bjd7cbspmembf0in.jpg)

Buzzwords aren’t something I expected when I started my career. In those days, most of the technology news arrived in paper-based weekly publications like InformationWeek and Network World. I remember thinking to myself, “Man, they are using these same words over and over again each week.”

That translated to people using buzzwords … all the time. Back then, my two favorite buzzwords were references to the internet as the “world wide web” and the “information superhighway.” I always wondered if there would be a super-duper-highway at some point.

However, recently, I noticed that buzzwords are used as placeholders where they don’t quite make sense. Terms like microservices, event-driven architecture, AI, and ML are used in contexts which leads me to conclude that many people don’t quite understand these terms. I didn’t expect this either…

Imagine this simple conversation related to a misunderstood question:

**Person #1:** What time does your flight leave?
**Person #2:** Later this year.

While Person #2 provides an answer that is not incorrect, the reply does not really yield any value to Person #1’s inquiry.

Along those same lines, the quest to migrate to microservices has endured similar challenges. More often than not, I have worked with clients and corporations whose “microservice” design resulted in a single monoservice. Basically, a monolithic application was replaced with a really big RESTful API.

For this publication, I thought it would be fun to walk through an example of creating a purpose-driven microservice design … the right way.

## The Purpose-driven Microservice Design

A purpose-driven microservice is a service that can stand on its own, and it can include a dedicated persistence store when required. By being purpose-driven, the microservice will provide a focused set of information and be the system of record for the data governed within the associated APIs.

By adopting the purpose-driven microservice approach, users can add additional nodes and scale down existing nodes in order to meet the needs of the API for that point in time. 

As an example, a purpose-driven microservice focused on an aspect of income taxes may see the highest usage during the first part of the year and require fewer instances running in the second half.

Let’s focus on the creation of a purpose-driven microservice design using a very simple example.

## Creating a Docker-based Microservice

The [Chinese Gender Predictor](https://www.thebump.com/chinese-gender-chart) is a grid system used to forecast the gender of a baby at birth. This is done by providing the month of conception and the mother’s current age at the time of conception. 

_Rumor has it that the Qing Dynasty imperial family relied on this same grid for the gender selection of sons, who were favored for the work and money they could provide for their families as well as for carrying on the family lineage._

Below is an illustration of the Chinese Gender Predictor grid:

![Chinese Gender Predictor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ll9n4bqd979fp1z10rn0.png)

As an example, an 18-year-old mother who conceived a child in January would produce a female baby.

For this publication, we’ll create a purpose-driven microservice that returns a gender prediction based on the same criteria. The resulting payload for the example above would appear as shown below:

```
{
    "month": 1,
    "age": 18,
    "gender": "female",
    "errorMessage": null
}
```

The microservice will utilize Java and Spring Boot and will employ a multi-stage Dockerfile to compile the service and build a Docker image that can host the birth-predictor APIs.

The code for the service can be found on GitLab at the following address:

https://gitlab.com/johnjvester/birth-predictor

## Creating a Reproducible Pattern Using Render Blueprints

I’ve written about the [Render](https://render.com/) platform in the following publications:

* [Using Render and Go For the First Time](https://dev.to/johnjvester/using-render-and-go-for-the-first-time-3ppk)
* [Under the Hood: Render Unified Cloud](https://dev.to/johnjvester/under-the-hood-render-unified-cloud-1672)

For my personal instances running on Render, I have used the Go programming language, static sites, and a Postgres instance. This time, I wrote the service in Java/Spring Boot. While native support for Java does not exist yet, the Render platform does include support for anything running in a Docker container.

Since the birth-predictor service includes a multi-stage Dockerfile, I wanted to see how easy it is to deploy a Docker-based service on the Render platform. However, I noticed the [Blueprint specification](https://render.com/docs/infrastructure-as-code) and wanted to see how that works, too.

### What is a Blueprint?

A Blueprint is Render’s implementation of Infrastructure as Code (IaC). IaC is also something I group into a larger concept called “* as Code”. Organizations that need to manage a deployment of several services or that have services requiring a lot of options can define their Render infrastructure (services, databases, and environment groups) as code in a render.yaml file.

### Using Render Blueprint

Building on the Blueprint example provided [here](https://render.com/docs/blueprint-spec#sample-blueprint-spec), I was able to quickly create a Blueprint for my Spring Boot services running via Docker containers:

```
services:
  - type: web
    name: restful-api-spring-boot
    env: docker
    region: ohio # optional (defaults to oregon)
    plan: free # optional (defaults to starter)
    branch: master # optional (uses repo default)
    numInstances: 1 # optional (defaults to 1)
    healthCheckPath: /actuator/health
    envVars:
      - key: SERVER_PORT
        value: 443
```

From there, I customized the YAML data for the birth-predictor service to update the name property and add a repo property, as noted below:

```
services:
  - type: web
    name: birth-predictor
    env: docker
    repo: https://gitlab.com/johnjvester/birth-predictor
    region: ohio # optional (defaults to oregon)
    plan: free # optional (defaults to starter)
    branch: master # optional (uses repo default)
    numInstances: 1 # optional (defaults to 1)
    healthCheckPath: /actuator/health
    envVars:
      - key: SERVER_PORT
        value: 443
```

This information was stored in the root of the `birth-predictor` repository, in a file called `render.yaml`. After committing and merging this change, the service was ready for deployment on the Render platform.

From the Render Dashboard, I selected the **New | Blueprint** option:

![New Blueprint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zslrbalg0ijv4tspeaku.png)

Next, I selected the birth-predictor repository, which I connected to my GitLab account using instructions found [here](https://render.com/docs/gitlab).

![Select Repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7209u6xyrev1gfqmsdiy.png)

Since I was using a Blueprint, all I had to do was provide a service group name for my new service:

![Name Service Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iajoi5sq4oxoqvzhmd89.png)

After pressing the **Apply** button, the deployment process started:

![Deployment in Progress](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3n5q43ctvxo83mmmbd0j.png)

A few minutes later, the service was deployed without any issues:

![Service Deployed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vugv3vlew9yam3awzngj.png)

## Birth Predictor in Action

With the birth-predictor service running, I can issue the following cURL command to obtain a new prediction:

```
curl --location --request POST 'https://birth-predictor.onrender.com/predict' \
--header 'Content-Type: application/json' \
--data-raw '{
    "conceptionMonth" : 11,
    "conceptionAge" : 43
}'
```

The resulting response payload looks like this:

```
{
    "month": 11,
    "age": 43,
    "gender": "male",
    "errorMessage": null
}
```

This information just happens to match the month of conception and the age of my wife at the time our son (Finny) was conceived. In August 2017, he arrived!


![Finny Arrives](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94fwo9atr6iwmfs9cq4w.jpg)

Just like they did during the Qing Dynasty, we were able to rely on the Chinese Gender Predictor to successfully forecast the sex of our child.

## Conclusion

Since 2021, I have been trying to live by the following mission statement, which I feel can apply to any IT professional:

> “Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.”
> - J. Vester

The Blueprints specification by Render adheres to my mission statement by allowing feature and service teams to focus on delivering against established goals and targets, without worrying about anything DevOps related. 

Once the service, component, or application is ready, teams merely need to include the render.yaml file in the root of their repository, then create a new service on the Render platform using the Blueprint option. Going forward, any updates to the connected repository will auto-deploy minutes after committing the code to the noted branch.

The Render platform lives by a Zero DevOps mentality, which is evident in the origin of the Blueprint concept. Feature and service developers want to—and should—be focused on delivering updates and functionality that provide the most value to their stakeholders. Render truly understands this reality.

I am certain that buzzwords will always be part of the technology space. However, understanding and adopting the true intention behind those buzzwords is something I hope technologists will pursue.

If you are interested in the source code for this publication, you can find it on GitLab at the following address:

https://gitlab.com/johnjvester/birth-predictor

Have a really great day!