# 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?](#what-is-soa)
* [Core Principles](#core-principles)
* [The Enterprise Service Bus](#the-enterprise-service-bus)
* [SOA vs Microservices](#soa-vs-microservices)
* [Service Contracts: WSDL and SOAP](#service-contracts-wsdl-and-soap)
* [Modern SOA Without the ESB](#modern-soa-without-the-esb)
* [When SOA Still Makes Sense](#when-soa-still-makes-sense)
* [Lessons Learned](#lessons-learned)

***

## 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

{% @mermaid/diagram content="graph TB
subgraph Consumers\["Service Consumers"]
WEB\[Web Application]
MOBILE\[Mobile App]
PARTNER\[Partner System]
end

```
subgraph ESB["Enterprise Service Bus"]
    ROUTE[Message Routing]
    TRANSFORM[Message Transformation]
    ORCHESTRATE[Orchestration]
    MONITOR[Monitoring]
end

subgraph Services["Business Services"]
    ORDER_SVC[Order Service]
    INVOICE_SVC[Invoice Service]
    CUSTOMER_SVC[Customer Service]
    NOTIF_SVC[Notification Service]
end

WEB --> ESB
MOBILE --> ESB
PARTNER --> ESB

ESB --> ORDER_SVC
ESB --> INVOICE_SVC
ESB --> CUSTOMER_SVC
ESB --> NOTIF_SVC

style ESB fill:#fff3cd" %}
```

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):

1. **Boundaries are explicit** — Services communicate only through defined interfaces. Internal implementation is hidden.
2. **Services are autonomous** — Each service manages its own lifecycle, deployment, and data.
3. **Services share schema and contract, not class or type** — Integration is through agreed data formats, not shared code libraries.
4. **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.

{% @mermaid/diagram content="sequenceDiagram
participant Client
participant ESB
participant OrderSvc as Order Service
participant InvoiceSvc as Invoice Service
participant EmailSvc as Email Service

```
Client->>ESB: Place Order (SOAP)
ESB->>ESB: Route + Transform
ESB->>OrderSvc: Create Order (internal)
OrderSvc-->>ESB: Order Created
ESB->>InvoiceSvc: Generate Invoice
InvoiceSvc-->>ESB: Invoice Ready
ESB->>EmailSvc: Send Confirmation
ESB-->>Client: Order Confirmed" %}
```

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:

| Aspect        | SOA                                   | Microservices                                            |
| ------------- | ------------------------------------- | -------------------------------------------------------- |
| 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

```xml
<!-- Simplified WSDL fragment -->
<definitions name="OrderService">
  <types>
    <xsd:element name="CreateOrderRequest">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="tenantId" type="xsd:string"/>
          <xsd:element name="items" type="tns:OrderItems"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </types>
  
  <portType name="OrderPortType">
    <operation name="createOrder">
      <input message="tns:CreateOrderRequest"/>
      <output message="tns:CreateOrderResponse"/>
    </operation>
  </portType>
</definitions>
```

**SOAP** (Simple Object Access Protocol) is the messaging protocol used to invoke those operations. It wraps a request in an XML envelope:

```xml
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <auth:SecurityToken>...</auth:SecurityToken>
  </soap:Header>
  <soap:Body>
    <CreateOrderRequest>
      <tenantId>restaurant_01</tenantId>
      <items>
        <item><productId>42</productId><quantity>3</quantity></item>
      </items>
    </CreateOrderRequest>
  </soap:Body>
</soap: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:

{% @mermaid/diagram content="graph TB
subgraph "Modern Service-Oriented Design"
GATEWAY\[API Gateway]

```
    ORDERS[Order Service]
    BILLING[Billing Service]
    NOTIFICATIONS[Notification Service]
    
    QUEUE[Message Queue / Event Bus]
end

DB1[(Orders DB)]
DB2[(Billing DB)]

GATEWAY --> ORDERS
GATEWAY --> BILLING
ORDERS --> DB1
BILLING --> DB2
ORDERS -->|OrderPlaced event| QUEUE
QUEUE --> NOTIFICATIONS
QUEUE --> BILLING" %}
```

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.
