Skip to content

PATTERN Cited by 1 source

Vendor abstraction service layer

When to use

You have:

  • A dependency on a particular third-party vendor for some capability your platform consumes.
  • A reasonable expectation that you may want to swap, add, or combine vendors later — for cost, capability, regulatory, or strategic reasons.
  • The vendor has opinionated quirks (auth flow, rate limits, batch sizes, payload schema, workspace identifiers, webhook formats) that you don't want leaking into the rest of your platform.

The pattern

Build a dedicated service whose primary responsibility is mediating between platform code and the third-party vendor. Everything platform-side that wants to talk to the vendor talks to this service instead. The service:

  1. Exposes a vendor-neutral domain API to the rest of the platform.
  2. Translates that API into vendor-specific calls.
  3. Owns the vendor's auth credentials, rate-limit awareness, retry/idempotency policy, and error-mapping.
  4. Is the only place that can be ripped out and replaced when the vendor changes.

The architectural goal: keep the rest of the platform vendor-shape-agnostic so a vendor swap is a one-service rewrite, not a platform-wide refactor.

Canonical instance — Instacart CRM Service

Verbatim from the 2026-05-14 source (sources/2026-05-14-instacart-scaling-personalized-marketing-for-multi-tenant-commerce-platforms):

"This service isolates provider-specific behavior behind a clean abstraction layer. That gives us flexibility to change providers in the future, support multiple providers at once, and avoid tightly coupling our core platform to any one vendor."

The CRM Service is the canonical instance. It:

  • Owns vendor knowledge: workspace identifiers, batch-API shape (≤50 users per call), per-retailer rate limits, auth.
  • Translates platform shapes to vendor shapes: incoming per-batch personalization request → vendor's specific batch- send API payload + per-retailer workspace targeting.
  • Owns idempotency policy at the at-least-once-streaming boundary so the rest of the platform doesn't need to care.
  • Is the only platform service that imports the vendor's SDK or schema.

The three goals named verbatim — change providers in the future, support multiple providers at once, avoid tightly coupling to any one vendor — define the pattern's success criteria.

Sibling patterns on the wiki

The wiki has other instances of the same architectural instinct, applied to different verticals:

  • patterns/ai-gateway-provider-abstraction — LLM provider abstraction (OpenAI / Anthropic / Bedrock / in-house). The AI gateway exposes a vendor-neutral inference API and routes per request to the right provider.
  • patterns/connector-library-as-protocol-abstraction — Unity Catalog's connector library that abstracts engine- specific commit semantics behind a clean engine ↔ catalog protocol so engines don't have to care whether the catalog is UC, Polaris, or HMS.

All three share the same shape: isolate the vendor's specific behavior behind one service, keep the rest of the platform vendor-agnostic, treat vendor neutrality as a first-class architectural goal.

Distinct from anti-corruption layer

DDD's anti-corruption layer is similar in mechanism but different in motivation. ACL exists to prevent a legacy system's vocabulary from polluting a new system. Vendor abstraction service layer exists to preserve future optionality — you may not even know yet that you'll swap the vendor; you build the layer because the option is cheap to keep open and expensive to retrofit.

What the layer typically encapsulates

Vendor concern Platform concern
Auth scheme (OAuth, API keys, SAML) Plain "send a message to user X"
Workspace identifiers, account IDs Tenant ID
Rate-limit headers + retry rules Backpressure / queueing strategy
Batch-size limits, payload format Domain object (campaign, shipment)
Webhook callback URLs Event/state transition
Vendor-specific error codes Domain error categories
SDK / HTTP client lifecycle Service-method signature

The platform's domain model stays clean; the vendor's quirks all live behind one boundary.

Caveats and tradeoffs

  • Lowest-common-denominator API. The vendor-neutral API can only expose features that all candidate vendors support — or it has to expose vendor-specific extensions, which leak the abstraction.
  • Performance overhead. The translation layer adds latency
  • serialization cost. Usually negligible vs the vendor's own API latency, but measurable.
  • The layer can become its own legacy. If the vendor- neutral API is over-designed for hypothetical multi-vendor futures that never come, the layer is just complexity.
  • Doesn't solve data lock-in. Workspaces, customer lists, templates inside the vendor are still non-portable; abstraction at the API layer doesn't help with vendor state. See patterns/per-tenant-workspace-in-third-party-saas for the data-portability tradeoff.

When NOT to use

  • The vendor is part of your unique value proposition (e.g. your platform sells "powered by Stripe" — abstracting that hides the value).
  • The vendor relationship is stable for foreseeable horizon (e.g. AWS for compute) and the optionality is unrealistically remote.
  • The vendor's API is already neutral (e.g. an industry- standard protocol like S3-compatible object stores).

Composes with

Seen in

Last updated · 542 distilled / 1,571 read