Skip to content

Services Overview

The ITsynch Suite 3.0 is composed of a set of microservices each providing a key feature of the Suite.

Each of this services is developed using the Suite Framework and are therefore composed by SuiteModules.

Introduction

A microservice is an autonomous unit which performs a single business process. They are usually composed of an HTTP API and event consumers and/or publishers.

The key feature of every microservice is that it is autonomous. Meaning that it can be ran by itself, only requiring its infrastructure components, like the Database.

Of course we will need to "connect" several microservices together somehow, and for that we'll cover different patterns that will allow us to do so in a decoupled way. We want to avoid coupling between these services as much as possible, since coupling is an impediment for growing fast.

Now, really microservices are just an abstraction; a set of patterns to follow. Deployment is irrelevant. One may think (or have been led to think) that one microservices equal one independent binary. Truth is microservices may or may not be deployed as a single process: splitting might be useful for scaling high traffic, but in our case we are mostly interested in the abstraction. Despite of this, we will have a bunch of binaries, since that also provides reliability. However, we do not need to worry from splitting APIs from event consumers for example; at least for now.

However, they do need to be able to be developed in isolation, meaning autonomous. So that means no hard-dependencies. In practice, that means that for a service to perform its business logic it cannot depend on other services directly. For example: when fetching an Inspection list from your service's database, you'd most likely want to get the reporter name (user name of the user who created it), and you might just reach out and directly query a Users service to get said user's info: this is a hard dependency; and should not be done in a microservices architecture.

The Suite 3.0 is an ecosystem. It is not a set of apps, or services, it is like a mesh, which is composed of multiple moving pieces working together to form a set of goals.

Microservices boundaries

For determining the boundaries of each service, we follow the definitions of Domain Driven Design.

Each Bounded Context may be composed of multiple microservices, sharing the Domain layer, and hence connecting to the same database.

Note

As mentioned in Data Consistency, only microservices within the same Bounded Context are allowed to share the same underlying data store.

Types of services

Even if they are all microservices, we can identify several kinds, depending on its main purpose.

Backend Services

A backend service is in charge of performing some business logic. It usually owns a business entity as well, like the Users Profile Service.

They are the deepest layer of our ecosystem, and are pretty abstract by themselves. They do not know the context in which they are going to be used, hence this kind of service does not perform any kind of authentication or authorization.

They do not have a concept of "current user" or "permissions" since that is application specific and should be handled at a higher layer.

These services are deployed in an internal network, which is not exposed to the internet the same way as a database would be.

Backend services need to keep a copy of the data they require to perform their business logic. This is what makes them autonomous. For example, if an Inspections service needs to be able to assign an Inspection to a User, it needs to have an entity in its service to represent User, which may be called perhaps InspectionAssignee or similar. The InspectionAssignee would be copied from the source of truth of Users, which makes the Inspection service have all the data it needs to perform its business logic.

Ground Rules

  1. no-hop rule: Backend Services cannot perform HTTP calls or other synchronous way of communication when required to perform their business logic. They usually keep a copy of the data they need to function, and keep it updated using async communication.
  2. own-database rule: Must have its own database, or the one of its Bounded Context.
  3. Cannot enforce authentication or authorization.
  4. Should be single purpose.

API Gateways

An API Gateway is a reverse proxy between clients and Backend Services. It is basically a middleman: instead of calling the API of a Backend Service, your application will usually call an API Gateway. This gateway may enforce certain rules, like authentication or authorization and it may modify the response it got from the Backend Service, if needed.

API Gateways may also do API Composition, which means in the context of a single incoming HTTP request, query multiple underlying Backend Services in parallel and aggregate their results into the incoming request response. However, this means that we are generating coupling between these services; if any of them goes down, we will have partial failure: the API Gateway will populate the fields of services that answered.

Warning

We do not recommend composing more than 2 or 3 services using this feature. If you feel the need to do so, most likely a Materialized View is the way to go.

Backend for Frontends

Backend for Frontends, or BFF for short, is an API Gateway which is specific for a certain Frontend. Basically, for each client application we will have a BFF. The BFF can be used to enforce authentication and authorization, which in this context we can, since this is application logic.

They are also used to compose and proxy requests to the underlying Backend Services , including the one(s) which represent the actual "application".

The BFF and API Gateway are useful for hiding the actual distribution of Backend Services from the Frontend. All your Frontend needs is to communicate with its BFF, and it handles the rest.

Application Services

We may identify another kind of service, which is used to enforce application logic. These Application Services will usually want to couple multiple Backend services to perform their business logic.

Most likely they will contain coordination logic, like Sagas. They are usually designed to fulfill the needs of a Frontend, for example if your application wants to provide a way to create an entity across multiple services, that distributed transaction needs to be handled by an Application Service.

Application Services usually won't own any real business data, they will depend on Backend Services for that.