← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Gateway Pattern

Code Quality Intermediate
debt(d7/e7/b7/t3)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no', and while phpstan and deptrac are listed as tools, they cannot automatically detect the absence of a gateway pattern — they can only flag direct external calls if custom rules are configured. The code_pattern describes scattered Guzzle/cURL calls and duplicated error handling, which requires deliberate architectural review to identify rather than standard automated analysis.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix describes creating a Gateway class as a single entry point, but the why_it_matters example (Stripe calls scattered throughout the codebase) and common_mistakes (scattered direct SDK calls, missing interfaces, fat gateways) indicate that remediation involves hunting down all direct external calls across multiple service classes, introducing interfaces, wrapping exceptions in domain exceptions, and restructuring — a cross-cutting refactor rather than a localised fix.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). The pattern applies across web, cli, and queue-worker contexts. Every interaction with an external system is shaped by whether a gateway exists — without it, every future feature touching that external system inherits the scattered-call problem. With it, the gateway becomes a load-bearing abstraction that every developer must be aware of and route through. The common_mistakes (one giant gateway, no interface, leaking exceptions) compound the structural weight if done poorly.

t3 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'minor surprise (one edge case)' (t3). The misconception field identifies a real but relatively subtle confusion — developers conflate Gateway with Adapter. Both wrap external interfaces, but the distinction (Gateway = external system access; Adapter = interface translation) is a documented gotcha rather than a catastrophic misdirection. The common_mistakes (leaking provider exceptions, fat gateways) add minor surprises but are not deeply counterintuitive to a competent developer.

About DEBT scoring →

Also Known As

service gateway API wrapper external service adapter

TL;DR

A class that encapsulates access to an external system or resource — wrapping HTTP APIs, queues, or legacy systems behind a clean interface that the rest of the application uses.

Explanation

A Gateway (Martin Fowler, PoEAA) isolates external dependencies behind an interface. PaymentGateway, EmailGateway, SMSGateway — each wraps one external system. Benefits: the application code never calls the HTTP client or SDK directly; the gateway can be mocked in tests; switching providers means only changing the gateway implementation. Similar to Adapter but typically wraps external systems rather than incompatible interfaces. Distinguished from Repository (data storage) by focusing on external service calls.

Common Misconception

Gateways and adapters are the same — both wrap external interfaces, but a Gateway specifically wraps access to external systems (APIs, queues); an Adapter translates between two existing interfaces.

Why It Matters

Without a gateway, Stripe's SDK is called directly throughout the codebase — switching to Braintree requires hunting down every Stripe call; with a gateway, only one class changes.

Common Mistakes

  • Gateway that leaks provider-specific exceptions — wrap them in domain exceptions.
  • Fat gateway with too much logic — gateways translate calls, not implement business rules.
  • Not defining a gateway interface — without an interface, mocking in tests requires more work.
  • One giant ExternalServiceGateway — one gateway per external system.

Code Examples

✗ Vulnerable
// No gateway — Stripe SDK scattered everywhere:
class OrderService {
    public function charge(Order $order): void {
        $stripe = new \Stripe\StripeClient(getenv('STRIPE_KEY'));
        $charge = $stripe->charges->create([
            'amount'   => $order->total->cents(),
            'currency' => 'gbp',
            'source'   => $order->paymentToken,
        ]);
        // Stripe-specific code in domain service
    }
}
✓ Fixed
// Gateway isolates the provider:
interface PaymentGateway {
    public function charge(Money $amount, string $token): PaymentResult;
}

class StripeGateway implements PaymentGateway {
    public function charge(Money $amount, string $token): PaymentResult {
        $charge = $this->stripe->charges->create([...]);
        return new PaymentResult($charge->id, $charge->status);
    }
}

// Domain service depends on interface:
class OrderService {
    public function __construct(private PaymentGateway $payments) {}
    public function charge(Order $order): void {
        $result = $this->payments->charge($order->total, $order->token);
    }
}

Added 16 Mar 2026
Edited 22 Mar 2026
Views 39
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 2 pings S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Amazonbot 7 Perplexity 5 Scrapy 4 Google 3 Ahrefs 3 Majestic 2 Unknown AI 2 Claude 2 Bing 2 Meta AI 1 PetalBot 1
crawler 28 crawler_json 4
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Create a Gateway class as the single entry point to an external system — all HTTP calls, data mapping, and error handling live in the gateway, keeping your domain code clean
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Direct Guzzle or cURL calls scattered across service classes; external API error handling duplicated in multiple places; no single abstraction for a third-party service
Auto-detectable: ✗ No phpstan deptrac
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update


✓ schema.org compliant