Anti-Corruption Layer
An anti-corruption layer translates between a legacy or external model and your domain model, preventing foreign concepts from leaking into and degrading your core design.
Definition
An anti-corruption layer is a translation boundary: façades, adapters, and translators convert the external system data model and semantics into your own model, and vice versa. It isolates the core domain from legacy schemas, third-party APIs, and partner conventions — accepting translation cost in exchange for protecting model integrity and change isolation.
Context and scope
Applied during strangler migrations, third-party ERP and CRM integrations, and wrapping external APIs whose models conflict with internal concepts. A DDD strategic pattern.
Common misconceptions
- It is just an adapter — adapters convert protocols; ACLs convert models and semantics, guarding conceptual integrity
- Translation belongs in the domain objects — translation in the domain pollutes it; the ACL keeps foreign vocabulary outside the boundary
- ACLs are migration scaffolding — many persist permanently around third-party systems you will never control
Anti-patterns
- Leaking external identifiers and enumerations through the layer and coupling the core to vendor vocabulary
- Building a one-to-one pass-through ACL that renames fields but imports the foreign model wholesale
- Writing ad hoc mapping code in every call site instead of concentrating it in the layer
Related concepts
Authoritative source
https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer
What it is
Your domain model embodies your competitive logic. An external system embodies someone else history. Connecting them naively lets the foreign model seep in — status codes that mean the wrong thing, identifiers with foreign lifecycles. The ACL is the customs office.
How it works
The layer exposes an interface in your terms. Internally, façades call the external system, translators map between models, and adapters handle protocol. Semantic mismatches become explicit mapping decisions: their one status code becomes your three states, their implicit pagination becomes your cursor contract.
When to use it
Strangler migrations reading and writing the legacy system, integrating vendor systems you cannot change, and consuming partner APIs with incompatible concepts. Skip it for well-aligned models where a thin client suffices.
Pitfalls
The layer accretes business logic by convenience — translation decisions drift into routing decisions. Bidirectional sync translations are subtle: round-tripping through two mappings can lose information; test round trips explicitly. The ACL needs its own tests with fixtures in both vocabularies.