PATTERN
Proxy layer for external SaaS¶
Pattern¶
Wrap an external SaaS dependency in an internal proxy service so that the rest of the internal API platform — specifically the aggregation tier that serves user-facing traffic — only ever calls Zalando-operated APIs (or $COMPANY-operated APIs, for the generalised form).
The proxy performs three jobs:
- Mapping — translate the SaaS's native content types into the company's internal API types (GraphQL, protobuf, internal REST schema), so consumers don't see the SaaS's schema directly.
- Caching — insulate the internal platform from the SaaS's per-second rate limits, latency tails, and per-request cost; serve repeated reads from the proxy.
- Resilience / isolation — the proxy is the only component that talks to the SaaS. A SaaS outage degrades gracefully against the proxy's cache and cannot cascade into arbitrary aggregation-tier consumers.
Why it matters¶
Without a proxy, every internal service that wants SaaS data must independently handle mapping, caching, rate limits, auth, and failure modes — duplicating integration logic and spreading the SaaS's blast radius across the fleet. The proxy concentrates all of that in one service with one operational owner, and the internal API-platform contract stays clean.
It also makes build-vs-buy reversible. If the team later decides to replace the SaaS (move off Contentful, switch CDNs, change payment providers), only the proxy's mapping layer changes — the internal GraphQL / REST contract stays stable for all consumers.
Canonical wiki instance — Zalando Contentful Proxy¶
The Contentful proxy sits between FSA (Zalando's GraphQL aggregator) and Contentful (the external headless CMS). It does all three jobs above, plus it is the enrichment join point where CMS-referenced IDs get resolved against Zalando's internal systems of record — see patterns/cross-surface-enrichment-via-internal-service.
The post's explicit motivation:
"This approach also ensures resilience and that the aggregation layer calls directly only Zalando-operated APIs."
Generalisation¶
The pattern is the default shape for any architecture where:
- An external SaaS owns a differentiated product (CMS, search, analytics, payments, fraud scoring, …), and
- The company has its own opinionated internal API platform (a GraphQL aggregator, a gRPC mesh, etc.), and
- The team wants the SaaS as an implementation detail of the platform rather than a visible dependency of consuming services.
The proxy-service seam is where the SaaS-vs-company contract lives.