System Design · Architecture Styles
Service-Oriented Architecture
is older than the microservices slogan. The idea is durable: compose a business from that expose , keep , and integrate through contracts—not through shared tables.
This note separates services from , contrasts ESB-era hubs with modern , and frames versus . The Microservices vs Monolith note covers when to split deployables; here we stay on SOA’s contract and ownership discipline—including how SOA is not automatically “lots of tiny services.”
SOA journey
Network only when independence pays.
Semantics + SLO, not just IDL files.
One team for API, data, and pages.
Pick workflow style on purpose.
What SOA is trying to buy
Classic enterprise pitch: web, mobile, partner portal, and call center all call the same Billing and Identity services. That reuse only works if the services are real capabilities with stable contracts—not if every channel reaches into the same SQL schema with a different ORM.
Interview framing: SOA is an integration and ownership style. Microservices are one way to implement fine-grained deployable services. You can practice SOA with a handful of coarse services (or even well-bound modules) and still get most of the architectural discipline.
Services versus modules
Read the diagram definition
flowchart TD
Need["Need independent scale / team / failure?"]
Need -->|No| Mod["Keep as module in one deploy"]
Need -->|Yes| Svc["Extract service + contract + data ownership"]
Mod --> API["In-process module API"]
Svc --> Net["Network contract + SLO"]
Svc --> Own["Bounded ownership + on-call"]
Bad["Skip straight to 40 tiny services"] --> Dist["Distributed monolith risk"]Promote a to a when you need independent scaling (image transcoding vs checkout), independent failure domains (search outage must not take down pay), or independent team release cadence. Until then, a modular monolith with enforced package APIs is often healthier SOA practice than twenty chatty pods.
Smell test: if service A cannot deploy without shipping B the same hour, and both write the same orders table, you have a . Fix ownership and contracts before drawing more boxes.
| Question | Module answer | Service answer |
|---|---|---|
| How do you call it? | Function / package API | HTTP, gRPC, events |
| Failure mode | Process crash shared | Timeouts, partial failure |
| Transaction | Local ACID easy | Saga / outbox needed |
| Ownership | Code owners + reviews | Team + on-call + SLO |
Contracts are the product
A is what other systems are allowed to depend on. IDL (OpenAPI, Protobuf) is necessary but insufficient. Spell out: idempotency, pagination, error codes, consistency (read-your-writes?), and compatibility policy.
Name services as : Catalog, Pricing, Fulfillment—not DataAccessLayerService. Technical layer services invite every product feature to become a cross-service transaction.
Contract checklist (interview-ready)
- Capability name + owner team
- Sync API and/or event types published
- Compatibility: additive default; version on break
- SLO: availability + latency for critical ops
- Failure: timeouts, retries, idempotency keys
- Data: who owns the system of record
- Anti-pattern ban: no shared writable DB with peersESB-era SOA versus modern mediation
Read the diagram definition
flowchart LR
subgraph Classic["ESB-era SOA"]
S1[Service A] --> Bus[Smart ESB]
S2[Service B] --> Bus
Bus --> S3[Service C]
Bus --> WF[Workflow + transforms]
end
subgraph Modern["Contract + mesh"]
A[Service A] -->|API / events| B[Service B]
A --> M[Mesh sidecar]
B --> M
M --> Pol[mTLS / retries / metrics]
endAn centralized routing, XML transforms, and sometimes the entire business process. Enterprises loved the governance story; operators hated the single point of cleverness. Upgrading the bus risked every integration. Debugging meant reading opaque mediation flows.
A revives “central policy” carefully: encryption, retries, identity, traffic shifting. Domain mapping belongs in services or dedicated workflow engines—not in Envoy filters stuffed with business rules. If your mesh config starts encoding “if SKU starts with X, reroute and mutate XML,” you rebuilt an ESB.
Many successful SOA shops use neither: plain gRPC + a gateway at the edge + async events. Mediation is optional infrastructure, not the architecture itself.
Bounded ownership beats org charts on paper
means one accountable team for a capability’s API, schema migrations, dashboards, and 3 a.m. pages. Conway’s law is not a bug: service boundaries that ignore team boundaries generate ticket ping-pong.
Anti-pattern: a platform team “owns” twenty business services while product teams only open PRs. Nobody has end-to-end authority; every incident is a meeting. Better: platform provides paved roads (templates, mesh, CI); product teams own capabilities.
as integration dissolve ownership. Two teams cannot evolve the same customer table safely. Publish events or query APIs; keep replicas read-only if you must project data elsewhere.
Orchestration versus choreography
Read the diagram definition
sequenceDiagram
autonumber
participant O as Orchestrator
participant Ord as Orders
participant Inv as Inventory
participant Pay as Payments
Note over O,Pay: Orchestration
O->>Ord: create order
O->>Inv: reserve
O->>Pay: charge
alt pay fails
O->>Inv: release
end
Note over Ord,Pay: Choreography
Ord->>Ord: OrderPlaced event
Ord-->>Inv: OrderPlaced
Ord-->>Pay: OrderPlaced
Pay-->>Inv: PaymentFailed event
Inv->>Inv: release on PaymentFailedPrefer when the workflow is a product feature you must explain, audit, and compensate centrally—checkout, KYC onboarding, money movement. Workflow engines (Temporal, Step Functions, Cadence-style) keep state explicit. Guard against the orchestrator becoming the new monolith: it should coordinate, not reimplement pricing and tax.
Prefer when multiple consumers genuinely react independently—analytics, notifications, search indexing on OrderPlaced. Publish well-versioned events; make handlers idempotent; invest in correlation ids. Without observability, choreography is “who broke checkout?” archaeology.
Hybrids are common: orchestrate the money path; choreograph side effects. That split is a strong interview answer.
Orchestration wins when…
- Compensations must be ordered and audited.
- Product needs one place to see “where is this order stuck?”
- Steps are few and owned by a workflow team.
Choreography wins when…
- Many independent consumers of the same fact.
- Producers should not know the consumer set.
- Eventual consistency is acceptable for those paths.
How SOA differs from “microservices”
Microservices culture emphasizes small independently deployable services, often with database-per-service and team autonomy. SOA historically emphasized enterprise capability reuse, coarser services, and formal governance—sometimes with an ESB. Overlap is huge; the slogans differ.
In interviews, say: both want contract-oriented composition. Microservices push granularity and autonomy further; SOA as a term does not require dozens of services. A company with five coarse capability services can be “doing SOA” well. A company with 200 endpoints that share one DB is doing neither.
| Lens | SOA emphasis | Microservices emphasis |
|---|---|---|
| Grain | Capability-sized, often coarse | Finer, team-sized services |
| Integration | Contracts; historically ESB | Smart endpoints, dumb pipes / mesh |
| Governance | Enterprise standards, reuse catalogs | Team autonomy + paved roads |
| Data | Varied; sometimes shared hubs | Prefer database-per-service |
Do not redo the full monolith trade-off tree here—that lives in Microservices vs Monolith. Use that note for deployability and modular monolith migration; use this note for contracts, ownership, mediation history, and workflow styles.
Worked example: retailer capabilities
Capabilities (SOA map)
Catalog — product truth, search projection via events
Cart — session cart; calls Pricing for quotes
Orders — system of record for purchases
Payments — PCI-ish boundary; idempotent charges
Fulfillment — warehouses; listens to OrderPaid
Workflow
Orchestrate: Cart → Orders → Payments (sync saga / workflow engine)
Choreograph: OrderPaid → Fulfillment, Email, Loyalty, Analytics
Ownership
Payments team owns API + ledger + on-call
Catalog owns SKUs; Fulfillment gets read models, not write access
ESB temptation
“Put stock checks and tax in the bus” → reject
Mesh may provide mTLS between Orders and Payments onlyFailure timeline: the smart bus that ate the company
t0 Teams publish SOAP services into a shared ESB t1 Bus grows transforms, retries, and “temporary” workflow t2 Black Friday: bus CPU saturates; every channel stalls t3 Hotfix needs bus team + three service teams on one call t4 Postmortem: business logic lived in mediation, not services t5 Migration: dumb pipes, capability APIs, workflow engine for checkout t6 Mesh later for mTLS—explicitly forbidden from hosting tax rules
Trade-offs to weigh
Coarse capability services vs fine microservices
Orchestration control vs choreography decoupling
Central mediation vs service-owned logic
Enterprise reuse vs team autonomy
Sync request chains vs async events
Choosing and explaining service-oriented architecture
A complete explanation connects the mechanism to a requirement. Describe what improves when you introduce it, which new failure cases become possible, and how you would know that the trade-off is worthwhile.
Explain the core idea
SOA composes business capabilities behind explicit network contracts and clear ownership—not behind shared databases.
Prefer modules until independent scale, failure, or team cadence justifies a service; avoid distributed monoliths.
ESBs centralized smart mediation; modern designs keep domain logic in services and limit meshes to network policy.
When it belongs
Multi-channel products need shared Billing, Identity, or Catalog capabilities.
You must choose orchestration vs choreography for a cross-service workflow.
Interviewers ask how SOA relates to—but is not identical with—microservices.
How it fails
Smart bus / ESB that owns workflows and saturates as a single point of failure.
Services that share writable schemas and must deploy as one unit.
Choreography without tracing or idempotency that produces undetectable lost updates.
Trade-offs to weigh
Coarse capability services versus fine-grained microservice autonomy.
Orchestrator visibility versus choreographed decoupling.
Central governance versus team speed.
Common misunderstandings
Equating SOA with “use an ESB” or with “must be microservices.”
Calling every JAR a service without a contract or owner.
Redoing the full monolith-vs-microservices debate instead of focusing on contracts and ownership.
Wrap-up
Exercises
- Draw capabilities. For a food-delivery app, list 5–7 capability services vs modules you would keep together. Justify each network boundary.
- Pick a workflow style. Refund after delivery failure: orchestration or choreography? Where do compensations live?
- ESB autopsy. Name three business rules that must never live in a mesh or bus, and where they belong instead.
Topic-specific references
- Hohpe & Woolf: Enterprise Integration Patterns — messaging styles behind SOA integrations.
- Fowler: Smart endpoints and dumb pipes — the post-ESB integration stance.
- Netflix architecture discussions — capability-oriented services at scale (context, not a template).
Key takeaway
SOA is contract-first composition of owned capabilities. Keep logic in services, mediation thin, modules first, and workflow style intentional—whether or not you brand the boxes “microservices.”