Service-Oriented Architecture (SOA)

📖 7 min read

Understanding SOA helps you recognize when a modern system is recreating its problems under new names.

Service-oriented architecture, in the form sometimes called orchestration-driven SOA, rose to prominence in large enterprises in the late 1990s and 2000s as an approach to enterprise integration. It organized systems around reusable services, stitched together by an orchestration engine and connected through an enterprise service bus (ESB). New systems rarely adopt full SOA today. Knowing how it worked still matters, both because many enterprises still run it and because its problems keep reappearing in systems that don’t call themselves SOA.

How It Worked

SOA built systems out of services meant to be reused across the enterprise. An orchestration engine composed them into business processes, and an ESB handled routing, transformation, and protocol mediation between them.

Layering

Orchestration-Driven SOA

Process services composed from shared services, with the orchestration engine and bus in the middle.

Orchestration-driven service-oriented architecture Consumers such as applications, partners, and user interfaces call coarse-grained process services such as Submit loan application. Process services run through the orchestration engine and enterprise service bus, which handle process flow, routing, transformation, and protocol mediation. The bus calls shared services such as Validate customer and Calculate credit score, and application-specific services that are not shared. Utility services for logging and security sit beneath everything. All communication flows through the bus, which makes it the central coupling point. Consumers: applications, partners, user interfaces Process services coarse-grained entry points for whole processes "Submit loan application" Orchestration engine and enterprise service bus process flow, routing, transformation, protocol mediation Shared service [shared, reused] Validate customer Shared service [shared, reused] Calculate credit score Application-specific service [not shared] single application only Utility services: logging, monitoring, authentication, authorization All communication flows through the bus, which makes it the central coupling point.

Services Designed for Reuse

SOA methodologies classified every service by how widely it would be reused, and vendors and methodologies each defined their own classification. The common thread was a split between two kinds of service. Process services were the coarse entry points that users and external systems called to run a whole business process, such as “Submit Loan Application” or “Process Insurance Claim.” Shared services implemented capabilities that many processes needed, such as “Validate Customer,” “Calculate Credit Score,” or “Check Inventory,” and each was meant to be built once and reused by every process that needed it. Utility services for logging, monitoring, and security sat underneath both, and capabilities too specific to share stayed inside the one application that used them.

Reuse was the promise that justified the whole structure. Every process that needed a capability would compose the shared service instead of rebuilding it.

Enterprise Service Bus

The ESB sat at the center of the system and took on a wide range of responsibilities:

  • Routing requests to the right services
  • Protocol mediation between HTTP, SOAP, and messaging protocols
  • Data transformation between services’ formats
  • Orchestration of multi-service workflows
  • Security such as authentication, authorization, and encryption
  • Monitoring through logging, metrics, and health checks

Because all communication flowed through it, the ESB became both a bottleneck and the system’s central coupling point. An ESB outage could stop every process that depended on it.

Orchestration Engine

Business processes were implemented as orchestrations that called shared services in sequence. The orchestrator knew the complete workflow, held its state, and handled errors and compensation. A “Submit Loan Application” process might call “Validate Customer,” then “Calculate Credit Score,” “Assess Risk,” “Determine Loan Terms,” and finally “Generate Offer Letter,” each as a separate service call coordinated by the orchestrator.

Why SOA Fell Out of Favor

Reuse created coupling. The more processes reused a shared service, the harder that service became to change, because every change had to be coordinated with every consumer.

The ESB became the coupling point it was meant to remove. It was supposed to decouple services, but centralizing routing, transformation, and orchestration made it a performance bottleneck, a single point of failure, and a dependency of every change.

The system was technically partitioned. The classification divided the system by technical role rather than by business domain. A single domain concept like “customer” ended up spread across process, shared, and application-specific services, so a change to how customers worked touched many services at once.

Everything tended to be one quantum. With a shared orchestration engine, a shared bus, and often shared databases behind the services, the parts of a SOA system could rarely be deployed, scaled, or failed independently.

The classification was rigid. Deciding whether a capability was a shared service or an application-specific one had major consequences, and teams could spend more effort classifying services than building them.

Vendor lock-in and complexity. Commercial ESBs were expensive and proprietary, so switching meant rewriting integration logic. Together with the classification scheme, the orchestration engine, and the SOAP and WS-* standards, even simple integration tasks could take enormous effort.

Where SOA Patterns Still Fit

Legacy Integration

ESB-style integration is good at connecting disparate legacy systems that were never designed to talk to each other. When dozens of legacy applications use different protocols, data formats, and security models, a central integration point can connect them without modifying each one.

Use that integration capability at the edges of a system rather than as its core architecture. New capabilities are better served by direct service communication, event streaming, and API gateways, with the integration layer reserved for bridging to legacy systems.

Established SOA Estates

Large enterprises with SOA that works well enough shouldn’t tear it out on principle. When replacing it would cost more than it returns, keep it and modernize around the edges, building new capabilities in other styles that integrate with the existing infrastructure.

Centralized Control Requirements

Some regulated environments require centralized control, detailed audit trails, and deterministic workflows. SOA’s orchestration model can provide that, so its patterns may still fit where regulation demands knowing and enforcing exactly what happens in every transaction.

Accidentally Rebuilding SOA

Signs a System Is Rebuilding SOA

Teams building microservices sometimes recreate SOA's problems without realizing it:

  • Shared libraries become shared services. When a shared domain library changes, every service must redeploy, which is the shared-service coupling problem under a different name.
  • API gateways become ESBs. The gateway starts with routing, then takes on transformation, then orchestration, then business logic, until it is an ESB in all but name.
  • Coordinator services become orchestration engines. A central service knows every endpoint, holds workflow logic, and manages state for the whole system.
  • Classification debates return. Teams argue about whether something is a "domain service" or an "infrastructure service" when the classification has no practical effect beyond constraining the design.

If services can't change independently because they share too much, the system has become SOA again, whatever its services are called.

When SOA Patterns Make Sense

Integrating many legacy systems that can’t communicate directly. Dozens of applications with different protocols, formats, and security models need to share data, and a central integration layer avoids modifying each one.

An established SOA estate that meets its needs. When the existing investment works, incremental improvement is usually a better bet than replacement.

Genuinely stable, widely reused capabilities. Some functions rarely change and are used everywhere, such as currency conversion or compound interest calculation, and those can work as shared services.

Regulation that requires centralized control and audit. Financial services, healthcare, and government systems sometimes need every transaction auditable and every policy provably enforced.

When to Avoid SOA

New systems that modern distributed styles fit better. Microservices, event-driven, and service-based architectures address the same needs with less coupling and complexity.

Independence and evolvability matter more than central control. When teams need to move quickly and deploy independently, SOA’s orchestration and service classification create friction.

Availability or scale that a central bus would cap. Interactions pass through the bus and the orchestration engine, so they limit throughput, and when either fails, everything that depends on it fails too.

No budget for heavy integration infrastructure. Message brokers, API gateways, and service meshes cover much of the same ground at lower cost.

Simple integration needs. Connecting a few services doesn’t justify an ESB. Direct service communication or a simple gateway is enough.

Evolution and Alternatives

Modernizing away from SOA:

Replace the ESB’s responsibilities piece by piece. Move external routing to an API gateway and service-to-service concerns to direct communication or a service mesh, so the bus stops being the center of everything.

Turn process services into domain-aligned services. Coarse-grained process services can become independently deployable services. Break the reuse habit where it creates coupling, even if that means some duplication.

Replace orchestration with choreography where it fits. For workflows that don’t need central control, services can react to events instead of being called in sequence by an orchestrator.

Modernize incrementally. Extract high-value, frequently changing capabilities first, leave stable functionality in place, and bridge old and new through gateways until the remaining SOA is small enough to retire or keep.

Found this guide helpful? Share it with your team:

Share on LinkedIn