Service-Oriented Architecture (SOA)
When I First Encountered SOA in the Wild
My first encounter with Service-Oriented Architecture was not in a tutorial or a book — it was inheriting a project at a company that had built their entire platform on an Enterprise Service Bus in the mid-2000s. WSDL contracts, SOAP envelopes, XML schemas hundreds of lines long, and a central bus that every system had to pass through.
It was bureaucratic, it was slow to change, and the ESB was a single point of failure for everything. I spent weeks understanding why the architecture existed before I could make any useful changes.
But I also came to understand what problem it was solving: connecting heterogeneous systems — different databases, different languages, different teams — through agreed contracts. The idea was sound. The implementation had grown rigid over years of accumulation.
SOA was the architectural standard of the enterprise era that preceded microservices. Understanding it is essential for working with legacy systems and for appreciating what microservices tried to fix.
Table of Contents
What Is SOA?
Service-Oriented Architecture organises software as a collection of loosely coupled services that communicate through standardised interfaces. Each service:
Exposes a contract (what it can do)
Is independent of the implementation of other services
Communicates through a common protocol (historically SOAP/HTTP, now REST or messaging)
Can be discovered and composed into larger processes
The ESB acts as the intermediary: routing messages, transforming formats, and orchestrating multi-service workflows.
Core Principles
The four core tenets of SOA (as described by Don Box at Microsoft):
Boundaries are explicit — Services communicate only through defined interfaces. Internal implementation is hidden.
Services are autonomous — Each service manages its own lifecycle, deployment, and data.
Services share schema and contract, not class or type — Integration is through agreed data formats, not shared code libraries.
Service compatibility is based on policy — Non-functional requirements (security, reliability, transactions) are expressed as policies, not baked into the service itself.
These principles are still sound. Modern microservices largely inherited them.
The Enterprise Service Bus
The ESB was the central component of classical SOA. It handled:
Routing: Deciding which service should handle a given message
Transformation: Converting between message formats (XML → JSON, SOAP → REST)
Protocol mediation: Bridging HTTP, JMS, FTP, etc.
Orchestration: Coordinating multi-step workflows across services
Message persistence: Reliable delivery with retry logic
In theory, the ESB freed services from knowing about each other. In practice, it concentrated complexity in one place and became a bottleneck requiring specialised knowledge to operate.
Every business workflow ran through this choke point. A bug in the ESB affected everything.
SOA vs Microservices
Microservices are often described as a reaction to the failures of SOA. The differences are real but often overstated:
Service size
Large, coarse-grained
Small, fine-grained
Communication
Central ESB
Direct service-to-service
Data
Services can share databases
Each service owns its data
Contracts
Formal (WSDL/SOAP)
Lightweight (REST/gRPC/events)
Orchestration
Centralised (ESB)
Decentralised (choreography or lightweight orchestrator)
Deployment
Often per-domain or per-business unit
Independent per service
Technology
Often homogeneous (Java EE)
Polyglot
The core insight micro services added was: remove the central bus and push intelligence to the edges. Services communicate directly, and each owns its own process and data store.
Service Contracts: WSDL and SOAP
Even if you never write a WSDL file, understanding what it is helps when working on enterprise integrations.
WSDL (Web Services Description Language) is an XML document that describes:
What operations a service exposes
The data types each operation accepts and returns
The network address and protocol to use
SOAP (Simple Object Access Protocol) is the messaging protocol used to invoke those operations. It wraps a request in an XML envelope:
This is verbose by today's standards. REST + JSON solved the verbosity problem but lost the formal contract guarantees that WSDL provided. OpenAPI/Swagger is the modern equivalent of WSDL for REST.
Modern SOA Without the ESB
The core ideas of SOA survive in modern architecture. What changed is the removal of the central bus:
Services still:
Expose explicit contracts (OpenAPI specs)
Own their data
Communicate through defined interfaces
But there is no single orchestrating bus. The API Gateway handles routing and the event bus handles async integration.
When SOA Still Makes Sense
Large enterprise environments where multiple teams or vendors own different services and coordination happens through contracts
Legacy system integration — connecting a modern system to 20-year-old backend systems that speak SOAP is often easier via an integration layer than a full rewrite
Regulated industries (banking, healthcare, government) where formal service contracts and audit trails are required by compliance
B2B integration where external partners need a stable, versioned interface regardless of your internal changes
Lessons Learned
The ESB was not the problem — centralisation was. The ESB accumulated too much responsibility over time. The lesson is to keep integration infrastructure thin.
Formal contracts are valuable. WSDL was verbose, but the idea — making the interface machine-readable and discoverable — is why we have OpenAPI today.
SOA at rest looks good; SOA in motion accumulates debt. Every shortcut taken in the ESB configuration became someone else's problem three years later.
Understanding SOA makes you a better microservices architect. Most "microservices problems" are SOA problems that were not solved and brought along for the ride.
Legacy does not mean wrong. If I need to integrate with a SOAP service today, I write the SOAP client and move on. I do not rewrite the service.
Last updated