A communications platform integrates many external providers. How does a ports-and-adapters structure help, and what is the design mistake that negates it?
Show the full answer Hide the answer
How it helps
The core defines ports — the operations it needs, expressed in its own terms — and each external provider gets an adapter implementing that port. The core knows nothing about any provider.
For a platform integrating many providers this delivers exactly what is needed:
- Provider peculiarities live in one place each, so adding a provider is bounded work that does not touch the core.
- The core is testable against in-memory adapters, without any provider.
- Providers are swappable, and a failing one can be routed around.
- Provider count scales linearly rather than accumulating branches in shared code.
The design mistake that negates it
Defining the port as the union of what providers offer, rather than as what the core needs.
It feels thorough and it inverts the dependency: the port now changes whenever any provider changes, which is precisely the coupling the structure exists to prevent. Every downstream component must handle fields that apply to one provider, and adding provider 301 changes code that providers 1 through 300 depend on.
The port must be defined from the inside. What does the platform's product need — send a message, learn its delivery state, know its cost? That contract changes rarely.
The second mistake
Abstracting away differences that are real and load-bearing. Delivery receipts that some providers never send, per-country regulatory identifiers, throughput ceilings differing by orders of magnitude. An adapter that quietly defaults a missing field turns a provider's limitation into a platform correctness problem nobody can attribute.
Model genuine differences as explicit capabilities the core can query, rather than as fields in the core model or as silent defaults.
The reliability dimension
Each adapter carries a reliability profile as configuration — timeout, retry budget, concurrency ceiling, circuit state, freshness tolerance. Tuning a degraded provider is then a configuration change rather than a code change, and one provider's bad day cannot consume the capacity of the fan-out.
The test
Adding provider 301 is bounded, repeatable work by one team, with no change to the core and no risk to the other 300. If it is not, the ports are defined from the outside and the structure is decorative.