Explainstuff.mebeta
All concepts
Cloud Native Patternsintermediate6 min

Anti-Corruption Layer

Put a translation layer between your clean model and a messy legacy system, so the old system's quirks never leak into your new code.

Ever inherited a system where the customer's name lives in a field called CUST_NM_1, dates are stored as eight-digit strings, and "deleted" really means a status flag set to 9? Now imagine building a clean, modern service that has to talk to that thing every day. Without care, its weirdness seeps into your beautiful new code until your model looks just as crusty as the old one.

The Anti-Corruption Layer is the firewall against that seepage. It's a dedicated translation boundary that lets your new system stay clean while still cooperating with the messy old one.

The problem

When two systems with different models talk directly, the stronger model usually wins — and it's rarely the one you want. If your new service calls the legacy system and uses its data shapes directly, those shapes spread through your codebase: the cryptic field names, the magic numbers, the assumptions baked in decades ago.

This is coupling at its worst. Your new system becomes dependent on details it shouldn't know about, and you lose the ability to evolve independently. The moment the legacy system changes, your clean code breaks — and over time, the corruption is complete: there's no clean model left to protect.

The legacy model wins
CUST_NM_1, status=9 leak in
New Service (corrupted)
Legacy System
Calling the old system directly lets its cryptic field names and magic numbers seep into the new service until no clean model is left.

How it works

An anti-corruption layer sits between the two systems as a dedicated translator. Your new service never speaks to the legacy system directly; it speaks to the ACL in its own clean vocabulary. The ACL then translates that request into whatever the legacy system expects, calls it, and translates the response back into your model on the way home.

Inside, the ACL is doing abstraction work: mapping customer.name to CUST_NM_1, parsing those eight-digit dates, turning status 9 back into a proper "deleted" flag. Your code stays blissfully unaware of all of it. The diagram below shows a clean request from the new service passing through the ACL, which converts it before reaching the legacy system — and converts the answer back on return.

A translator between two worlds
translated request
New Service
Anti-Corruption Layer
Legacy System
The new service speaks its own clean model; the layer converts to and from the legacy system so its quirks never leak in.
Tip

Keep the ugliness in one place. The whole point is that all the gnarly mapping logic lives inside the ACL and nowhere else. If translation rules start leaking into your domain code, the layer isn't doing its job — tighten the boundary.

When to use it

An ACL shines during incremental migrations. You're carving a microservice out of a monolith, or replacing a legacy platform piece by piece, and the two must coexist for a while. The ACL quarantines the old system so the new one can grow cleanly — and when the legacy system finally retires, you delete the layer and your model is left pristine. It pairs well with the strangler-fig approach to gradual replacement.

It's also the right tool whenever you integrate with an external third-party API whose model you don't control: wrap it in an ACL so vendor quirks never become your problem. The trade-off is a real one — it's another component to build, test, and maintain, and it adds a little latency per call. For two systems that already share a clean, stable model, an ACL is just overhead you don't need.

Key takeaways

  • An anti-corruption layer (ACL) is a translation boundary between a new system and a legacy or external one.
  • It converts requests and data between the two models so each side keeps its own clean design.
  • It stops a legacy system's quirks, bad names, and odd data shapes from leaking into your new code.
  • It's a cornerstone of incremental migration: the new system grows while the old one stays quarantined behind the layer.
  • The cost is an extra component to build and maintain, plus a little latency on each translated call.

Keep going