Stackbook Logo
architecture-descriptionestablished · medium operational burden

Anti-Corruption Layer

Also known as: acl, translation-layer

Intent

Isolate a new model from a legacy or external system by translating between their models at a boundary.

Problem

A new service must integrate with a legacy system or third-party API whose model is awkward or inconsistent. Letting those concepts leak in pollutes the new domain model and couples it to the foreign system.

Forces

  • •Legacy models use different names, units and semantics
  • •The new domain model should stay clean
  • •The external system may change or be replaced
  • •Translation adds code and latency

Solution

Overview

An Anti-Corruption Layer (ACL), from domain-driven design, protects a clean model from an external one. The new system speaks its own language internally; the ACL translates at the border so legacy concepts never spread.

How it works

The ACL has three parts: a facade the domain calls, translators that convert between models, and adapters that talk to the foreign protocol (SOAP, flat files, a vendor SDK).

Domain --> CustomerGateway (facade)
              |
         Translator: LegacyCust -> Customer
              |
         Adapter --> legacy CRM (SOAP)

For example, the legacy CRM returns a status code of "A", "I" or "X" and a combined name field. The translator maps these to an enum ACTIVE, INACTIVE, CLOSED and splits the name into first and last. Writes flow the opposite way. The ACL can be a library inside the service or a standalone service when several consumers share it.

Pitfalls

  • Letting foreign types cross the facade. If domain code imports a legacy class, the layer has failed.
  • Putting business rules in translators. They should map, not decide.
  • Neglecting contract tests. Record real foreign responses and verify translators against them.
  • Treating it as permanent when it was meant for migration; plan its removal.
  • Ignoring error translation. Map foreign errors and timeouts into domain-level failures.

Key takeaways

  • Translate at the boundary so the domain keeps its own vocabulary.
  • Expose one facade; keep foreign types behind it.
  • Use contract tests against captured foreign payloads.
  • Pairs naturally with incremental migration of legacy systems.

✓ When to Use

  • •Integrating with a legacy system during migration
  • •Consuming a third-party API with a poor or unstable model
  • •Two bounded contexts with conflicting vocabularies

✗ When Not to Use

  • •The external model already matches yours
  • •Throwaway integrations with short lifespan
  • •Simple pass-through of a few fields

Pros

  • +Domain model stays clean
  • +Foreign changes absorbed in one place
  • +Eases later replacement of the legacy system

Cons

  • −Extra layer to build and test
  • −Added latency and mapping overhead
  • −Translation bugs can be subtle

Cost Profile

Infrastructure

Low - library or small service

Operational

Medium - keep mappings in sync

Cognitive

Medium - requires domain-modelling discipline

Failure Modes

  • Translator silently drops or mistranslates fields

  • Layer grows into a business-logic dumping ground

  • Foreign types leak past the facade

Real-World Examples

Alternatives

    Related Patterns

      Competency Domains

      distribution communicationeconomics evolution