The Anti-Corruption Microservice Pattern

Implement an anti-corruption microservice (ACM) to talk to an external system. Other microservices only communicate with the external system via the ACM. The ACM translates requests from the microservices system to the external system and back.

Use this pattern when you employ a microservices architecture and you want to ensure their designs are not limited by an external system. This pattern is an adaptation of the Anti-Corruption Layer (ACL) pattern for microservices architectures.

Context and problem

The context of the ACL pattern applies, but additionally, your application is made up of microservices and multiple of those communicate with the external system. If you’d only apply the ACL pattern, then you’d end up with multiple microservices that each have an ACL for the same external system.

Solution

Isolate the microservices from the external system by placing an Anti-Corruption Microservice (ACM) between them. This layer translates communications between the application’s microservices on the one hand and the external system on the other.

The diagram above shows an application consisting of 4 microservices, 3 of which communicate with the same external system via an Anti-Corruption Microservice. Communication between the microservices and the ACM always uses the data model and architecture of the application. Calls from the ACM to the external system conform to the external system’s data model and methods. The ACM contains all the logic necessary to translate between the two systems.

Issues and considerations

  • The ACM may add latency to calls between the two systems. Conversely, by caching data from calls by one microservice, the ACM might speed up calls by a different microservice.
  • The ACM is another microservice to be managed, maintained, and scaled.
  • The ACM doesn’t need to support all the features of the external system, just the ones used by the application’s microservices.

When to use this pattern

Use this pattern when:

  • Two or more systems have different semantics, but still need to communicate.
  • The external system is provided by a vendor and you want to minimize vendor lock-in. This elevates the idea of hexagonal architecture to the microservices world, where the ACM is a port and the external system an adapter.

Related resources

Acknowledgements

Thanks to Dev for pushing me to write up this pattern.

Pre-OSGi modularity with Macker

OSGi is gaining a lot of traction lately. But what if you have a very large application? Migration can be a lot of work.

I would like to point to a simple tool we use that might help out a bit here. It’s called Macker and

it’s meant to model the architectural ideals programmers always dream up for their projects, and then break — it helps keep code clean and consistent.

Macker is open source (GPL). It’s current version is 0.4 and has been for a long time. That doesn’t mean it’s immature or abandoned, however. It’s author had a lot more features planned, hence the 0.4. But what’s already available is enough to give it a serious look.

So, what does Macker do, exactly? It enforces rules about your architecture. For example, suppose you have a product with a public API. You could create a rule file with an <access-rule> that the API must be self-contained:

  <message>The API should be self-contained</message>
  <deny>
    <from pattern="api" />
  </deny>
  <allow>
    <from pattern="api" />
    <to pattern="api" />
  </allow>
  <allow>
   <from pattern="api" />
    <to pattern="jre" />
  </allow>

These rules can be very explicit about what is and what isn’t allowed. There are several ways to specify them, but I’ve found it easiest to use patterns, like in the example above, since they can have symbolic names. Here’s an example:

<pattern name="api">
  <include class="com.acme.api.**"/>
</pattern>

Where the ** denotes every class in the com.acme.api package, or any of its sub-packages. See the Macker user guide for more information about supported regular expressions.

Macker comes with an Ant task, so you can enforce your architecture from your build. Maybe not as good as OSGi, but it sure helps with keeping your code the way you intended it.