Learning outcome
By the end of this lesson, you should be able to explain the difference between Adapter and Facade, spot which one fits a checkout integration, and justify the boundary in a design interview. The core idea is simple: Adapter changes one interface into another, while Facade simplifies access to a subsystem. In payment-provider work, that difference affects dependency direction, how much the checkout orchestration knows about the provider, and how easy future migrations will be.
Intuition
Imagine a checkout service that needs to charge a card, reserve inventory, and create an order. A payment provider might expose a callback-heavy, provider-specific API with concepts like intent IDs, capture windows, and error codes. A Facade can sit inside your application and present a clean checkout-oriented flow such as “authorize payment,” “capture payment,” and “void payment.” A consumer-facing team uses the Facade to avoid juggling provider details.
An Adapter is different. It is useful when your code already expects a specific interface, but a payment provider ships a different one. The Adapter translates between the two so existing code can keep using its preferred shape. In other words, the Adapter is about compatibility; the Facade is about simplification.
Deep dive
The easiest interview test is to ask: “What is the source of friction?” If the friction is a mismatch between two interfaces, think Adapter. If the friction is that a subsystem is too complicated to use directly, think Facade.
Dependency direction matters:
- With an Adapter, your application code often depends on an abstraction it already understands, and the Adapter depends on the provider API.
- With a Facade, your application code depends on the Facade, and the Facade depends on multiple internal services or provider calls.
In a checkout orchestration example, a Facade can coordinate the whole checkout boundary: payment authorization, inventory reservation, fraud checks, and order creation. It protects the rest of the app from “who do I call first?” complexity. That is especially useful when the orchestration is business logic owned by your system.
By contrast, an Adapter is a good fit when your checkout service has an internal payment port, but the provider speaks a different dialect. You may already have a PaymentGateway abstraction, and a provider-specific implementation translates provider request/response models into your domain types. The Adapter does not decide business flow; it only translates.
A useful rule: if you removed the external provider tomorrow, would the class still make sense as a business entry point? If yes, it is probably a Facade. If no, and it mostly exists to translate APIs, it is probably an Adapter.
When neither pattern is needed
Sometimes the best boundary is no extra pattern at all.
- If the provider API is already simple and your app only makes one or two direct calls, adding a Facade can be needless indirection.
- If your own interface already matches the provider exactly, an Adapter adds ceremony without value.
- If the checkout flow is tiny and stable, the extra layer may slow understanding more than it helps.
Use patterns to reduce complexity, not to decorate architecture.
Failure modes
Common interview mistakes include:
- Calling everything a Facade just because it sits in front of something external.
- Saying an Adapter “hides complexity” without noting that its main job is interface conversion.
- Mixing orchestration with translation in one class and then being unable to explain why it exists.
- Forgetting that a Facade can depend on multiple subsystems, while an Adapter usually bridges one target interface to one adaptee.
- Treating migration from one payment provider to another as automatically requiring a Facade; sometimes an Adapter around a stable port is enough.
Migration trade-offs are important. A Facade can make it easier to swap internal steps because callers only know the simplified boundary. But if your application leaks provider-specific concepts through the Facade, migration becomes harder. An Adapter can support provider replacement behind a stable interface, but only if the interface itself is domain-oriented and not overly coupled to the provider’s vocabulary.
Interview drill
Use these four scenario questions to sharpen your answer.
- Scenario: The checkout service already exposes
AuthorizePayment, but a new provider usesCreateIntentandConfirmIntent. Which pattern fits?
Answer: Adapter. The problem is a mismatch between your expected interface and the provider’s API.
- Scenario: The checkout flow must call fraud screening, payment, inventory, and receipts, and the rest of the app should not know the sequence.
Answer: Facade. The problem is coordinating and simplifying a subsystem boundary.
- Scenario: The provider API is simple, and the checkout code only needs one direct charge call.
Answer: Neither pattern may be necessary. Direct integration may be clearer.
- Scenario: Your team wants to replace the payment provider next quarter without changing the checkout orchestration code.
Answer: Prefer a domain-oriented port plus an Adapter per provider. If the orchestrator is also simplifying multiple internal steps, you may additionally use a Facade at the checkout boundary.
Decision checklist
Ask these questions in order:
- Am I translating one interface into another, or simplifying access to a subsystem?
- Does the class mainly map request/response shapes, or does it coordinate business steps?
- Should callers depend on provider details, or on a stable domain boundary?
- Will this layer help future provider migration, or just add indirection?
- Can I explain the class’s job in one sentence without using both “translate” and “orchestrate” at the same time?
Revision checklist
Remember these compact distinctions:
- Adapter = compatibility layer.
- Facade = simplified entry point.
- Adapter changes form; Facade changes experience.
- Adapter usually bridges one interface to one implementation.
- Facade can coordinate multiple services or provider calls.
- Neither pattern is required when the direct integration is already clear and stable.
In interviews, lead with intent, then dependency direction, then trade-offs. That sequence shows you understand not just the labels, but the reason the boundary exists.