345 Systems recently participated in API World in San Jose (https://apiworld.co/), showcasing the significance of microservices in today’s technological landscape. The conference delved into the integration of APIs and microservices, emphasizing their role in building efficient solutions. While microservices have gained immense popularity, it’s essential to reflect on their connection to Service-Oriented Architecture (SOA) principles. Despite SOA being prominent a decade ago, the excitement around microservices suggests a need for a closer examination of past implementation practices. This article explores the historical context and nuances that differentiate microservices from their SOA predecessors.
Microservices are a really hot topic at the moment, and people are jumping on the bandwagon really quickly.
An observation I make in this regard is that microservices, to me, are simply a restatement of SOA principles. SOA was a big thing 10-15 years ago, so why is it that we are now getting so excited about microservices?
I have a theory that it’s because when SOA came out most people did SOA wrong. We used to build enterprise systems with distributed layers (COM+/MTS on Windows vs CORBA / Java EE / EJB on other platforms). After this, we entered a new world of web services, usually based on SOAP / XML, that allowed us to connect services over HTTP instead. This gave advantages in terms of ease of connectivity, navigation of Ǔrewalls, Internet connectivity, multi-site WAN connectivity etc. My contention is that for many people SOA was confused with web services. People used web services as a means of writing remote procedure calls (RPCs), without adopting SOA principles.
If you look back at any SOA architecture theory from back then you’ll find that autonomy of services was already an essential architectural element. The point was that you should be able to connect to an SOA service and all you would need to know was the signature of the API and the rest of the service, whether it be back-end processing, data storage or logic, would be hidden behind the service façade. The technology used to implement the service would be irrelevant as open protocols were used.
Sound familiar? With the exception that interfaces now have coalesced around REST and JSON instead of SOAP and XML is beside the point. This is implementation detail. The important architectural concept is the same. Microservices encapsulate a piece of logic, do a specific thing and do it well. Crucially, they do not expose any dependencies on other systems. This is good SOA practice that we’ve been striving for.
Perhaps one of the things that has changed perceptions is the hosting model, and the move from hosted servers to cloud computing. Cloud-based web applications tend to align closely with the microservice mindset because of the way cloud deployments tend to force you into deploying services as independent units.
In the old hosted server model, a server was a significant investment: it takes capital and ongoing resources to keep a server running in your datacenter, and so the natural inclination is to get the most out of each server. Many organisations therefore use a model where many web services are deployed onto a single server to maximize the use of that server. Whilst this makes sense form the resource-allocation perspective it means that dependencies for one web service can be inadvertently shared across all other services on the same machine. The same goes for operating system updates and drivers, let alone dealing with the impact of competing load on machine resources. Scalability in this hosting model is constrained by the need to size for the maximum workload of all of the combined services hosted on the machine.
The cloud model is different. Hosting instances, whether they be vCPUs or micro virtual machines, have no inherent capital cost. They attract a usage-based charge, but you right-size them to the workload you need, meaning that they achieve an efficiency of resource allocation in a different way. If you host a single service on a cloud instance you have control of the dependency stack, meaning that updates for one microservice cannot bleed into the dependency stack of another microservice. Each service is independently horizontally scalable through the addition of more instances, meaning that scalability is easier to achieve, but also right-sizing is easier as each microservice is sized to its own needs and not to the needs of the collective load.
Of course, there are still pitfalls. From a dependency perspective, one of the most important features of a microservices architecture is the isolation of data. This is also one of the main errors that I have seen with implementing web services in enterprises. People think that if they have 10 web services all pointing at the same database they’ve “done SOA”, even though they’ve introduced a nightmare of cross-dependencies. You Ǔnd that you can’t upgrade one service because the others can’t handle the change in database schema. Then you Ǔnd you need to upgrade them all at once, which effectively results in the monolithic deployment you were trying to get away from in the first place.
So the move to microservices not only needs to achieve isolated services in terms of scale and software-stack dependencies, but also isolation of data dependencies.
An early casualty of this architectural change of HTTP APIs is you lose the world of ACID transactions. This can be scary for people who have taken comfort in the certainty of transactional integrity for most of their professional life. However, designing for eventual consistency instead of ACID consistency is a liberating change. ACID forces synchronicity and serialization, and synchronicity is the destroyer of scalability. If you truly want to scale you have to design for each instance being stateless and autonomous.
All of which we were saying about SOA 15 years ago. What’s changed is that the tech to support it has become a whole lot easier.