Sayantam Dey on Product Development

Lessons from Service Oriented Architecture (SOA)

May 23, 2021
Guitar lessons

Photo by Jacek Dylag on Unsplash

SOA invokes mixed feelings amongst Software Architects and Developers. It began with a promise but ended up confusing people. Over the second half of the last decade, there have been crucial lessons from the SOA experience.

First, the good parts of SOA.

A Promising Manifesto

Service Orientation is the basis of the SOA Manifesto. Service Orientation supposedly helps organizations deliver value with changing business needs. The tenets of the manifesto are as follows:

  • Business value over technical strategy
  • Strategic goals over project-specific benefits
  • Intrinsic interoperability over custom integration
  • Shared services over specific-purpose implementations
  • Flexibility over Optimization
  • Evolutionary refinement over pursuit of initial perfection

The SOA manifesto made the mistake of combining strategic and tactical tenets. The manifesto would be ever relevant if it did not include intrinsic interoperability and shared services. Still, it got right the part of aligning technology with business and prioritizing business value.

Meaningful Design Principles

SOA design principles align with object-oriented (OO) programming, SOLID principles, and other software development practices. Briefly, the principles are as follows:

  • Services should have formal or standardized contracts.
  • Services should be loosely coupled from their environment as well as impose low consumer coupling.
  • Services should not expose non-essential information.
  • Services express agnostic logic and are reused across the enterprise.
  • Services have autonomous logical and runtime boundaries. Logical autonomy leads to a service contract that does not overlap with other services.
  • Services minimize statefulness.
  • Services are discoverable.
  • Services are composable. This principle is connected to the principle of reusability.

The tricky aspect of the design principles is achieving harmony between loose coupling and reusability.

Services as Basic Building Blocks

SOA encourages the functional decomposition of a business into services which are the basic building blocks. The typical service types are as follows:

  • Task Service - A non-agnostic context corresponding to a business process such as "submit an invoice." A task service will usually incorporate one or more agnostic services to complete its task.
  • Entity Service - A reusable business agnostic service associated with an entity such as "Invoice."
  • Utility Service - A reusable technology-specific service with an agnostic context such as logging, notification, or security.
  • Microservice - A non-agnostic service with a small functional scope and specific processing requirements.

A service is said to be 'agnostic' if it implements a generic functionality that other services may reuse. For example, a User entity service is an agnostic service because, by itself, it can't perform a complete business task. A service is said to be 'non-agnostic' when its purpose is to perform a business task. This type of service is not reusable.

These services are typically layered, where each service type corresponds to one layer. Thus, there would be an entity service layer, a business (task) service layer, etc.

Next, the reasons for the mixed feelings.

High Coordination Efforts

The prevalent SOA practice was to assign the responsibility of each service layer to a different team. For example, one team would manage the entity services, and another would manage business (task) services. This team topology increased the coordination efforts for every change because a single business change would change all layers and activate all developers in the organization. It's as if a small pebble dropped in the middle of a lake rippled in all directions. A modern variation of this is the front-end and back-end team.

Slow and Brittle Systems

Services as basic building blocks is a fine idea, except when everything is treated as a service. As per the SOA manifesto, services should use standardized contracts. This tenet leads to inter-service calls using SOAP over HTTP(s), where WSDL defines the service contract. The inter-services communication over HTTP increases the latency of each request and fails to recover gracefully from HTTP timeouts or unavailability. These mistakes follow from the fallacies of distributed computing and lead to Distributed Monoliths - a black hole that will absorb every business function.

Long Rollout Windows

The focus on reusable services leads to the God object anti-pattern. An entity service tends to get used differently in different business contexts. When these various contexts are part of the same interface, it breaks interface segregation and violates the single responsibility principle. As such, a change to an Entity service could potentially break multiple business services that depend on it. This ripple effect inevitably increases the regression time, delaying releases and leading to the infamous weekend deployments.

Bright Lights of Big Tech

The final piece of discontent was when Big Tech got on the SOA bandwagon to sell their ESBs. ESBs worsened the situation because they moved business logic outside of the services into adapters that would bridge incompatible business functions. In any case, the adapters had to be tested in their isolated context. The isolated context for testing was not helpful because the tests would pass even if a service had changed its contract in a backward incompatible manner. Testing the adapters in a connected fashion meant that businesses would have to invest in maintaining replica QA environments where adapters connect to the same systems but non-production data.

Five Lessons to take Forward

How can we benefit from SOA and learn from the mistakes? These are five lessons to remember.

  • It is far more important for a service to be autonomous than reusable or composable. When designing autonomous services, each concept or piece of data must belong to only one service or reside in a shared kernel. The application layers exist within a service, not the other way round.
  • Align teams around a logical grouping of services (or one service) instead of service layers to minimize coordination costs and create cross-functional teams.
  • Splice entities across the services instead of creating one service for each entity. For example, instead of a User entity service, create an Administrator entity for the administration service and a custom Customer entity for the shopping cart, billing, and shipping services. Each service only stores the customer's information meaningful to its operation - a shopping cart may only keep the essential details such as name, billing may store preferred payment method, and shipping may store only shipping addresses.
  • Avoid service-to-service calls to not fall for the fallacies of distributed systems and end up with a distributed monolith. Autonomous services inform other services of completed tasks with events. An event should ideally transmit only the identifiers and not business attributes because the latter case would leak business context to other services.
  • Avoid an ESB if you have control over at least one system that needs to be part of the brokerage. Split the system under control across logical services, and each service can interact with its own logically aligned external system.
Enjoyed this post? Follow this blog to never miss out on future posts!

Related Posts

⏳

Authentication and Authorization with AWS - API Gateway
Dec 29 2021

AWS Cognito User Pools and Federated Identities can be used to authorize API gateway requests.

⏳

Authentication and Authorization with AWS - Federated Access
Nov 21 2021

AWS Cognito Identity Pools provide authenticated users access to AWS resources.

⏳

Authentication and Authorization with AWS - Cognito SAML Integration
Nov 14 2021

AWS Cognito integrates with a corporate identity provider such as Active Directory (AD) using SAML.

⏳

Authentication and Authorization with AWS - About IAM
Sep 12 2021

Amazon Web Services (AWS) references a dizzying number of concepts, resources, patterns, and best practices to provide a fully managed…

⏳

Message Delivery Guarantees with ActiveMQ
Aug 17 2019

Apache ActiveMQ is a mature messaging middleware.

⏳

Authentication and Authorization with AWS - Cognito Sign-up and Sign-in
Oct 17 2021

Amazon Web Services (AWS) provides Cognito to delegate authentication and authorization out of applications completely.

⏳

Flux-CD Pattern for AWS CDK8s Services
Jul 9 2023

AWS Cloud Development Kit for Kubernetes called generates Kubernetes manifest files for Kubernetes () deployments and services.

⏳

How Headless CMS work
Jun 25 2023

Headless CMSs came about because it is hard to build a single platform that content writers like using and software developers like…

⏳

How this Blog Works
Nov 15 2020

I find myself scratching my head everytime I need to explain the inner workings of my blog. It is not because it is special or complex.

⏳

Technical Decisions that you'll Regret Later
Jan 28 2024

Software development Teams make many decisions while building systems.