SOAP: Simple Object Access Protocol

Why This Matters

In 2024, you might think SOAP is dead. REST dominates public APIs, GraphQL powers modern apps, and gRPC handles microservices. So why learn SOAP?
Because SOAP still powers critical infrastructure:
  • Banking systems: 70% of financial transactions worldwide
  • Healthcare: HIPAA-compliant patient record exchanges
  • Government: IRS, Social Security, DMV systems
  • Enterprise ERP: SAP, Oracle, Salesforce integrations
  • Airline reservations: Global Distribution Systems (GDS)
When you see "SOAP" in a job description, it means working with mission-critical legacy systems that process billions of dollars daily. These systems won't be rewritten—they'll outlive REST and GraphQL.
By the end of this deep-dive, you'll understand:
  • Why SOAP uses XML instead of JSON (spoiler: it's not just verbosity)
  • How WS-Security provides enterprise-grade encryption and signatures
  • When SOAP beats REST (yes, really!)
  • How to integrate with legacy SOAP services from modern Go applications
Real-world impact: A single SOAP API misconfiguration at a major bank can expose millions of customer records or cause multi-million dollar transaction failures. Understanding SOAP isn't optional for enterprise developers—it's essential.

What SOAP Solves

Enterprise Requirements That REST Doesn't Address

1. Built-In Security Standards
REST relies on external standards (OAuth, JWT):
http
# REST: Security bolted on Authorization: Bearer <token> # No standard for message encryption, signing, or token format
SOAP has WS-Security built into the protocol:
xml
<!-- SOAP: Security is part of the message --> <soap:Envelope> <soap:Header> <wsse:Security> <wsse:UsernameToken> <wsse:Username>user</wsse:Username> <wsse:Password Type="PasswordDigest">...</wsse:Password> </wsse:UsernameToken> <ds:Signature><!-- XML Digital Signature --></ds:Signature> <xenc:EncryptedData><!-- Encrypted payload --></xenc:EncryptedData> </wsse:Security> </soap:Header> <soap:Body>...</soap:Body> </soap:Envelope>
2. ACID Transactions Across Services
REST has no standard for distributed transactions:
Service A: Update account balance Service B: Record transaction # If Service B fails, how do you rollback Service A?
SOAP has WS-AtomicTransaction:
xml
<soap:Header> <wsat:CoordinationContext> <wsu:Identifier>txn-123</wsu:Identifier> <wsat:CoordinationType>WSAT11:2PC</wsat:CoordinationType> </wsat:CoordinationContext> </soap:Header> <!-- Two-phase commit across multiple services -->
3. Formal Contract (WSDL)
REST: No standard contract format
# Developer reads docs, hopes they're up-to-date GET /api/users/{id} # What fields does it return? # What's the exact format?
SOAP: Machine-readable contract (WSDL)
xml
<wsdl:definitions> <wsdl:types> <xsd:schema> <xsd:element name="GetUserRequest"> <xsd:complexType> <xsd:sequence> <xsd:element name="userId" type="xsd:int"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </wsdl:types> </wsdl:definitions> <!-- Auto-generate client code in any language -->
4. Reliable Messaging
REST: No standard for guaranteed delivery
POST /api/payment # Did it succeed? Network timed out # If I retry, will I double-charge?
SOAP with WS-ReliableMessaging:
xml
<wsrm:Sequence> <wsrm:Identifier>seq-123</wsrm:Identifier> <wsrm:MessageNumber>5</wsrm:MessageNumber> </wsrm:Sequence> <!-- Guaranteed exactly-once delivery, message ordering -->

Real-World Scenarios Where SOAP Excels

  1. Banking Transactions: ACID guarantees, security, audit trails
  2. Healthcare Systems: HIPAA compliance, patient data encryption
  3. Government Services: Legal compliance, formal contracts
  4. Legacy Integration: SAP, Oracle, IBM systems
  5. High-Security Environments: Defense, finance, critical infrastructure

How SOAP Works

SOAP is a protocol (unlike REST, which is an architectural style). It defines:
  • Message structure (XML envelope)
  • Communication patterns (request/response, one-way, async)
  • Extension standards (WS-Security, WS-Transactions, etc.)

SOAP Message Structure

xml
<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:example="http://example.com/services"> <!-- Optional: Metadata, security, routing --> <soap:Header> <example:Authentication> <example:Username>admin</example:Username> <example:Password>secret</example:Password> </example:Authentication> </soap:Header> <!-- Required: Actual data --> <soap:Body> <example:GetUserRequest> <example:UserId>123</example:UserId> </example:GetUserRequest> </soap:Body> </soap:Envelope>
Response:
xml
<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Body> <GetUserResponse> <User> <Id>123</Id> <Name>Alice Smith</Name> <Email>alice@example.com</Email> </User> </GetUserResponse> </soap:Body> </soap:Envelope>

SOAP vs REST: Communication Flow

Note over Client,SOAP Server: SOAP Request

Note over Client,SOAP Server: SOAP Request

WSDL: The API Contract

WSDL (Web Services Description Language) defines:
  • Types: Data structures (XML Schema)
  • Messages: Input/output parameters
  • Port Types: Operations (like function signatures)
  • Bindings: Protocol details (SOAP over HTTP)
  • Services: Endpoint URLs
xml
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"> <!-- Data types --> <types> <xsd:schema> <xsd:element name="GetUserRequest"> <xsd:complexType> <xsd:sequence> <xsd:element name="userId" type="xsd:int"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="GetUserResponse"> <xsd:complexType> <xsd:sequence> <xsd:element name="user" type="tns:User"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </types> <!-- Messages --> <message name="GetUserRequestMsg"> <part name="parameters" element="tns:GetUserRequest"/> </message> <message name="GetUserResponseMsg"> <part name="parameters" element="tns:GetUserResponse"/> </message> <!-- Operations --> <portType name="UserService"> <operation name="GetUser"> <input message="tns:GetUserRequestMsg"/> <output message="tns:GetUserResponseMsg"/> </operation> </portType> <!-- Binding (SOAP) --> <binding name="UserServiceSOAP" type="tns:UserService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetUser"> <soap:operation soapAction="http://example.com/GetUser"/> <input><soap:body use="literal"/></input> <output><soap:body use="literal"/></output> </operation> </binding> <!-- Endpoint --> <service name="UserService"> <port name="UserServicePort" binding="tns:UserServiceSOAP"> <soap:address location="http://example.com/soap/users"/> </port> </service> </definitions>

WS-* Standards Ecosystem

Diagram 2

Diagram 2

Remote Procedure Call with Contracts

Think of SOAP like calling a function on a remote server with a formal contract:
Local Function Call:
go
user := GetUser(123) // Type-safe, compiler checks signature
SOAP:
xml
<GetUser> <userId>123</userId> </GetUser> <!-- WSDL defines exact signature, tools generate code -->
REST:
http
GET /users/123 # No formal contract, rely on documentation
Key Difference:
  • SOAP: Contract-first (WSDL defines API, code generated)
  • REST: Code-first (write code, document API)

Deep Technical Dive

1. Code Example: SOAP Server in Go

Using go-soap/soap library:
go
package main import ( "encoding/xml" "log" "net/http" "github.com/fiorix/wsdl2go/soap" ) // User represents a user entity type User struct { XMLName xml.Name `xml:"User"` ID int `xml:"Id"` Name string `xml:"Name"` Email string `xml:"Email"` } // GetUserRequest SOAP request type GetUserRequest struct { XMLName xml.Name `xml:"http://example.com/services GetUserRequest"` UserID int `xml:"UserId"` } // GetUserResponse SOAP response type GetUserResponse struct { XMLName xml.Name `xml:"http://example.com/services GetUserResponse"` User User `xml:"User"` } // SOAPEnvelope represents SOAP message structure type SOAPEnvelope struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` Body SOAPBody `xml:"Body"` } type SOAPBody struct { XMLName xml.Name `xml:"Body"` Content interface{} } // UserService implements SOAP operations type UserService struct { users map[int]User } func NewUserService() *UserService { return &UserService{ users: map[int]User{ 123: {ID: 123, Name: "Alice Smith", Email: "alice@example.com"}, 456: {ID: 456, Name: "Bob Jones", Email: "bob@example.com"}, }, } } func (s *UserService) GetUser(req GetUserRequest) GetUserResponse { user, exists := s.users[req.UserID] if !exists { user = User{ID: req.UserID, Name: "Unknown", Email: ""} } return GetUserResponse{User: user} } // SOAP HTTP Handler func (s *UserService) SOAPHandler(w http.ResponseWriter, r *http.Request) { // Parse SOAP envelope var envelope SOAPEnvelope if err := xml.NewDecoder(r.Body).Decode(&envelope); err != nil { http.Error(w, "Invalid SOAP request", http.StatusBadRequest) return } // Extract request (simplified - real impl needs reflection) requestXML, _ := xml.Marshal(envelope.Body.Content) var getUserReq GetUserRequest xml.Unmarshal(requestXML, &getUserReq) // Execute operation response := s.GetUser(getUserReq) // Build SOAP response responseEnvelope := SOAPEnvelope{ Body: SOAPBody{Content: response}, } // Send response w.Header().Set("Content-Type", "application/soap+xml; charset=utf-8") w.WriteHeader(http.StatusOK) xml.NewEncoder(w).Encode(responseEnvelope) } // WSDL Handler (serves WSDL contract) func (s *UserService) WSDLHandler(w http.ResponseWriter, r *http.Request) { wsdl := `<?xml version="1.0"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://example.com/services"> <types> <xsd:schema targetNamespace="http://example.com/services"> <xsd:element name="GetUserRequest"> <xsd:complexType> <xsd:sequence> <xsd:element name="UserId" type="xsd:int"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="GetUserResponse"> <xsd:complexType> <xsd:sequence> <xsd:element name="User" type="tns:User"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="User"> <xsd:sequence> <xsd:element name="Id" type="xsd:int"/> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Email" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> </types> <message name="GetUserRequestMsg"> <part name="parameters" element="tns:GetUserRequest"/> </message> <message name="GetUserResponseMsg"> <part name="parameters" element="tns:GetUserResponse"/> </message> <portType name="UserServicePort"> <operation name="GetUser"> <input message="tns:GetUserRequestMsg"/> <output message="tns:GetUserResponseMsg"/> </operation> </portType> <binding name="UserServiceBinding" type="tns:UserServicePort"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetUser"> <soap:operation soapAction="http://example.com/GetUser"/> <input><soap:body use="literal"/></input> <output><soap:body use="literal"/></output> </operation> </binding> <service name="UserService"> <port name="UserServicePort" binding="tns:UserServiceBinding"> <soap:address location="http://localhost:8080/soap"/> </port> </service> </definitions>` w.Header().Set("Content-Type", "text/xml") w.Write([]byte(wsdl)) } func main() { service := NewUserService() http.HandleFunc("/soap", service.SOAPHandler) http.HandleFunc("/soap?wsdl", service.WSDLHandler) log.Println("SOAP server starting on :8080") log.Println("WSDL available at http://localhost:8080/soap?wsdl") log.Fatal(http.ListenAndServe(":8080", nil)) }

2. Code Example: SOAP Client in Go

go
package main import ( "bytes" "encoding/xml" "fmt" "io/ioutil" "net/http" ) // SOAP structures (same as server) type SOAPEnvelope struct { XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` Body SOAPBody `xml:"Body"` } type SOAPBody struct { XMLName xml.Name `xml:"Body"` Content interface{} } type GetUserRequest struct { XMLName xml.Name `xml:"http://example.com/services GetUserRequest"` UserID int `xml:"UserId"` } type GetUserResponse struct { XMLName xml.Name `xml:"http://example.com/services GetUserResponse"` User User `xml:"User"` } type User struct { XMLName xml.Name `xml:"User"` ID int `xml:"Id"` Name string `xml:"Name"` Email string `xml:"Email"` } func callSOAPService(userID int) (*User, error) { // Build SOAP request request := SOAPEnvelope{ Body: SOAPBody{ Content: GetUserRequest{UserID: userID}, }, } // Marshal to XML requestXML, err := xml.MarshalIndent(request, "", " ") if err != nil { return nil, err } // Add XML declaration soapRequest := []byte(xml.Header + string(requestXML)) // Send HTTP POST resp, err := http.Post( "http://localhost:8080/soap", "application/soap+xml; charset=utf-8", bytes.NewBuffer(soapRequest), ) if err != nil { return nil, err } defer resp.Body.Close() // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } // Parse SOAP response var responseEnvelope struct { Body struct { GetUserResponse GetUserResponse } } if err := xml.Unmarshal(body, &responseEnvelope); err != nil { return nil, err } return &responseEnvelope.Body.GetUserResponse.User, nil } func main() { user, err := callSOAPService(123) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("User: ID=%d, Name=%s, Email=%s\n", user.ID, user.Name, user.Email) }

3. WS-Security Example

Adding authentication and digital signatures:
xml
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <!-- Username Token Authentication --> <wsse:UsernameToken> <wsse:Username>admin</wsse:Username> <wsse:Password Type="PasswordDigest">VGhpcyBpcyBhIGhhc2g=</wsse:Password> <wsse:Nonce EncodingType="Base64Binary">MTIzNDU2Nzg=</wsse:Nonce> <wsu:Created>2026-01-27T10:30:00Z</wsu:Created> </wsse:UsernameToken> <!-- Digital Signature --> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="..."/> <ds:SignatureMethod Algorithm="..."/> <ds:Reference URI="#body"> <ds:DigestMethod Algorithm="..."/> <ds:DigestValue>...</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>...</ds:SignatureValue> <ds:KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI="#X509Token"/> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> <!-- X.509 Certificate --> <wsse:BinarySecurityToken EncodingType="Base64Binary" ValueType="X509v3" wsu:Id="X509Token"> MIICxjCCAa4... </wsse:BinarySecurityToken> </wsse:Security> </soap:Header> <soap:Body wsu:Id="body"> <GetUserRequest> <UserId>123</UserId> </GetUserRequest> </soap:Body> </soap:Envelope>
Security Features:
  • Authentication: Username/password with digest (not plaintext)
  • Integrity: Digital signature ensures message not tampered
  • Non-repudiation: Signer can't deny sending message
  • Encryption: Can encrypt entire body or specific elements

4. SOAP Faults (Error Handling)

xml
<soap:Envelope> <soap:Body> <soap:Fault> <soap:Code> <soap:Value>soap:Sender</soap:Value> <soap:Subcode> <soap:Value>UserNotFound</soap:Value> </soap:Subcode> </soap:Code> <soap:Reason> <soap:Text xml:lang="en">User with ID 999 not found</soap:Text> </soap:Reason> <soap:Detail> <ErrorDetails> <ErrorCode>404</ErrorCode> <Timestamp>2026-01-27T10:30:00Z</Timestamp> </ErrorDetails> </soap:Detail> </soap:Fault> </soap:Body> </soap:Envelope>

When to Use: Decision Framework

Diagram 3

Diagram 3

Use SOAP When:

  • Enterprise security: WS-Security, message encryption, digital signatures
  • ACID transactions: WS-AtomicTransaction for distributed transactions
  • Formal contracts: WSDL-first development required
  • Legacy integration: Existing SAP, Oracle, IBM systems
  • Compliance: HIPAA, PCI-DSS, SOX require audit trails
  • Financial services: Banking, insurance, stock trading

Don't Use SOAP For:

  • Public APIs: Too complex for third-party developers
  • Mobile apps: XML payloads too large, battery drain
  • Real-time apps: Too much overhead for low latency
  • Modern microservices: gRPC is faster, REST is simpler

Common Pitfalls

Pitfall 1: Not Validating Against WSDL

The Mistake: Sending invalid XML that doesn't match WSDL schema.
The Fix: Use WSDL tools to generate client code automatically.

Pitfall 2: Forgetting Namespaces

The Mistake:
xml
<GetUserRequest> <!-- Missing namespace! --> <UserId>123</UserId> </GetUserRequest>
The Fix:
xml
<tns:GetUserRequest xmlns:tns="http://example.com/services"> <tns:UserId>123</tns:UserId> </tns:GetUserRequest>

Pitfall 3: Not Handling SOAP Faults

The Mistake: Only checking HTTP status (always 200, even for errors).
The Fix: Parse SOAP Fault from body when present.

Performance Implications

SOAP vs REST Payload Size:
REST:
json
{"id": 123, "name": "Alice", "email": "alice@example.com"} // 59 bytes
SOAP:
xml
<soap:Envelope> <soap:Body> <GetUserResponse> <User> <Id>123</Id> <Name>Alice</Name> <Email>alice@example.com</Email> </User> </GetUserResponse> </soap:Body> </soap:Envelope> // 250+ bytes (4x larger!)
Optimization:
  • Use MTOM (Message Transmission Optimization Mechanism) for binary data
  • Enable gzip compression
  • Cache WSDL parsing

Real-World Use Cases

Use Case 1: Banking Wire Transfers

xml
<soap:Envelope> <soap:Header> <wsse:Security><!-- WS-Security --></wsse:Security> <wsat:CoordinationContext><!-- Transaction --></wsat:CoordinationContext> </soap:Header> <soap:Body> <WireTransfer> <From>123456789</From> <To>987654321</To> <Amount currency="USD">10000.00</Amount> </WireTransfer> </soap:Body> </soap:Envelope>
Requirements met:
  • ACID transaction (rollback if fails)
  • Encryption (WS-Security)
  • Non-repudiation (digital signature)
  • Audit trail (message logging)

Use Case 2: Healthcare HL7 Integration

SOAP used for patient record exchange between hospitals (HIPAA-compliant).

Use Case 3: Government Tax Filing

IRS uses SOAP for e-filing tax returns (formal contract, security).

Interview Questions

Junior Level

Q: What is SOAP? A: SOAP (Simple Object Access Protocol) is an XML-based protocol for exchanging structured information in web services. Unlike REST, it has formal contracts (WSDL) and built-in security standards.
Q: What's the difference between SOAP and REST? A: SOAP is a protocol with formal contracts (WSDL), uses XML only, and has built-in security/transactions. REST is an architectural style, uses JSON/XML, and relies on HTTP methods.

Mid Level

Q: Explain WSDL and its purpose. A: WSDL (Web Services Description Language) is an XML document that describes a SOAP service's operations, input/output types, and endpoint locations. It's like an API contract that allows automatic code generation.
Q: What is WS-Security and why is it important? A: WS-Security is a SOAP extension for authentication, encryption, and digital signatures. It's important for enterprise systems requiring message-level security (not just transport-level HTTPS).

Senior Level

Q: When would you choose SOAP over REST or gRPC? A: SOAP when you need: (1) WS-* standards (Security, Transactions), (2) Formal contracts required by compliance, (3) Legacy enterprise integration (SAP, Oracle), (4) ACID transactions across services.
Q: How would you integrate a modern Go microservice with a legacy SOAP system? A: (1) Use WSDL to generate Go client code, (2) Create adapter service that exposes REST/gRPC and calls SOAP internally, (3) Handle XML marshaling/unmarshaling, (4) Implement retry logic for unreliable SOAP services, (5) Cache WSDL parsing.

Key Takeaways

  1. SOAP is a protocol, REST is a style - SOAP is more rigid, REST is flexible
  2. WSDL provides formal contracts - machine-readable API definition
  3. WS- standards for enterprise features* - Security, Transactions, Reliable Messaging
  4. XML-only, more verbose - 3-5x larger payloads than JSON
  5. Not dead, powers critical infrastructure - banking, healthcare, government
  6. Best for enterprise integration - legacy systems, compliance requirements
  7. Poor for public APIs - too complex, large payloads
  8. ACID transactions with WS-AtomicTransaction - distributed two-phase commit
  9. Message-level security with WS-Security - encryption, signing, authentication
  10. Use REST for new projects, SOAP for legacy - unless enterprise requirements demand SOAP

Further Learning

  1. Practice: Integrate with a public SOAP service (weather, currency)
  2. Tools: Learn SoapUI for testing SOAP services
  3. Read: WS-* specifications (WS-Security, WS-ReliableMessaging)
  4. Enterprise: Study SAP, Oracle SOAP APIs
  5. Migration: Learn REST wrapper patterns for SOAP services
SOAP may not be trendy, but understanding it is essential for working with enterprise systems that process trillions of dollars annually. Master SOAP, and you'll be invaluable for legacy integration and enterprise projects.
All Blogs
Tags:soapxmlenterpriseapi-designinterview-prep