The Critical Role of API Orchestration in Composable Systems
Composable architecture has a dirty secret: the independence that makes it appealing also makes it genuinely difficult to operate. When you decompose a monolith into 15 independent services, each team can deploy and scale their service freely. But every user-facing feature that crosses service boundaries — and in a real e-commerce or SaaS product, almost every feature does — requires coordinating those independent services into a coherent response. Without a deliberate coordination layer, composable systems devolve into a fragile mesh of point-to-point calls that is slower, harder to debug, and more brittle than the monolith it replaced.
API orchestration is the coordination layer that makes composable architectures actually work in production. It is not an API gateway — it does not just route requests. It is not a service mesh — it does not manage network policies. API orchestration is the logic that says: given this inbound request, call these three services in parallel, wait for all responses, transform the data, apply this fallback if service B is slow, and return a single unified response. It is the glue that transforms a collection of independent services into a product that users can actually use.
What API Orchestration Is Not
Before understanding what orchestration does in composable systems, it helps to be precise about what it is not. This distinction matters because teams often believe they have solved the coordination problem when they have actually only solved part of it.
An API gateway handles ingress concerns: authentication, rate limiting, SSL termination, routing by path. It does not know about your business logic. It cannot fan out to three services in parallel and merge the results. A gateway is a necessary infrastructure component, but it does not solve service coordination.
A service mesh handles the network layer between services: mutual TLS, service discovery, load balancing, retry policies at the transport level. It gives each service reliable connectivity to others, but it does not know that your product page needs data from the catalogue, pricing, and inventory services simultaneously. Service mesh is infrastructure; orchestration is business logic.
GraphQL federation is a schema composition approach that solves the problem of presenting a unified schema to clients. It can fan out to multiple subgraphs, but the coordination logic is implicit in the schema — it is not easily configurable per-request, and it does not handle synchronous orchestration of REST APIs, webhooks, and databases that composable commerce platforms typically need.
API orchestration is different from all three. It sits between the edge and your services, and its job is to implement the coordination logic your composable system needs: which services to call for each workflow, in what order, with what data, how to handle failures, how to transform and merge responses. This logic is specific to your business and changes as your product evolves.
The Coordination Problem in Composable Systems
Consider a composable e-commerce product page. A fully composable implementation might have separate services for: product catalogue, inventory management, pricing engine, recommendation engine, review aggregation, shipping estimator, and personalisation. Each service is independently deployed, independently scaled, and owned by a separate team. This is exactly the composable promise.
But when a user loads a product page, they expect to see all of this information together: the product details, the current stock status, the price (which may be customer-specific), relevant recommendations, recent reviews, available shipping options, and perhaps a personalised promotion. The user does not care how many services are involved. They care that the page loads fast and shows accurate, consistent information.
Without orchestration, the question becomes: who coordinates these seven service calls? The options are: the frontend client (which means seven sequential or parallel calls from the browser, with complex error handling logic duplicated in every client), a custom BFF written by hand (which requires building and maintaining connection pooling, retry logic, caching, credential management, and observability from scratch), or an orchestration layer (which handles the infrastructure and lets you focus on defining which services to call and how to merge their results).
The coordination problem compounds as the system grows. At 7 services it feels manageable. At 20 services, the number of potential cross-service interactions grows quadratically. The engineering cost of managing those interactions without a coordinated orchestration layer is one of the primary reasons composable architectures struggle to deliver on their promises in practice.
How Orchestration Solves It: Parallel Execution
The most immediate benefit of an orchestration layer in composable systems is parallel execution. When the product page needs data from seven services, an orchestration layer identifies which calls are independent and fans out to all of them simultaneously. The response time becomes approximately equal to the slowest individual service, not the sum of all services.
In practice, the difference is dramatic. If each of seven services takes 80–120ms to respond, sequential calls would produce a 560–840ms response time — slow enough to meaningfully hurt conversion rates. Parallel execution reduces this to 80–120ms — the same latency as calling a single fast service. The composable architecture, which might have appeared to introduce a performance penalty, now delivers the same performance as a monolith while maintaining all its flexibility.
Parallel execution in a production orchestration layer is more nuanced than simply calling all services at once. Data dependencies between calls create natural sequencing requirements. If the pricing engine needs to know the customer's loyalty tier before it can return a customer-specific price, and the loyalty tier comes from a customer service call, then those two calls must be sequential. But the inventory check and the recommendation engine call are independent of the pricing call — they can run in parallel with it. A well-designed orchestration layer understands these dependency relationships and automatically maximises parallelism while respecting the required sequencing.
Handling Partial Failures in Composable Responses
One of the trickiest problems in composable systems is what to do when some services succeed and others fail. In a monolith, a database query either works or it does not — the failure mode is binary. In a composable system, you can have four services returning successfully and two timing out, and you need to decide what the user-facing response looks like.
Without orchestration, this decision is made implicitly in client code, often inconsistently. The web frontend might show an empty recommendations section when the recommendation service fails. The mobile app might show an error for the entire product page. The partner API integration might return a 500 error. Each client makes the decision independently, leading to different user experiences for the same underlying failure.
An orchestration layer centralises this decision. You define, per service call, whether the call is required (failure means the entire response fails), optional (failure means that section is omitted from the response), or cacheable (failure means use the last cached response). This policy is defined once in the orchestration workflow and applied consistently regardless of which client is making the request. The web frontend, mobile app, and partner API all see the same degradation behaviour under the same failure conditions.
This consistency is operationally significant. When the recommendation service starts failing in production, the on-call engineer knows exactly what users will see: product pages load successfully but without recommendations. There is no need to audit each client to understand the impact, because the behaviour is defined in one place.
Observability: Where Composable Systems Typically Fall Short
Composable architectures are often well-instrumented at the service level — each team has dashboards, logs, and alerts for their own service. The gap is at the cross-service level. When a user reports that the product page was slow, the investigation requires correlating logs from seven different services, owned by seven different teams, with different logging formats and different clock synchronisation. This is where composable systems most visibly fail to deliver on their promise of operational simplicity.
An orchestration layer provides a single execution timeline for every request that passes through it. This timeline shows: which services were called, when each call started, how long each took, what was returned, whether any retries occurred, and what the final composed response looked like. When someone reports a slow product page, the orchestration log shows immediately whether the slowness came from the pricing engine (200ms), the recommendation service (340ms), or the inventory API (15ms with a cache hit). The investigation that would take an hour of log correlation takes 30 seconds.
This observability is not just useful for debugging — it is essential for performance optimisation. The execution timeline reveals which services are consistently the bottleneck, which cache TTLs are too short (causing unnecessary upstream calls), and which services would benefit most from circuit breaking because their error rate is elevated. In a point-to-point composable architecture, this data is scattered across service logs and requires active correlation. In an orchestrated architecture, it is available for every request by default.
BFF Layers as Channel-Specific Orchestration
Backend-for-Frontend (BFF) layers are a specific application of orchestration that is particularly valuable in composable systems. The insight behind BFF is that different client channels — mobile app, web frontend, partner API, in-store kiosk — have different data requirements even when accessing the same underlying composable services. A single unified API that serves all channels inevitably over-fetches for some and under-fetches for others.
A mobile BFF uses the orchestration layer to call the same composable services as the web BFF, but shapes the response differently: smaller image URLs, fewer fields, mobile-optimised pagination. The web BFF might request high-resolution images, full product descriptions, and richer filtering metadata. The partner API BFF might add additional fields like cost prices and supplier information that are only relevant to B2B integrations. All three BFFs call the same underlying composable services — the orchestration layer is what makes it practical to maintain these channel-specific response shapes without duplicating service integration logic.
When the product catalogue service adds a new field, each BFF team can independently decide whether to include it in their channel's response. The orchestration layer absorbs the upstream API change — the consuming BFFs are insulated from the catalogue service's API evolution. This is how composable architectures should work: independent services that can evolve independently, with an orchestration layer that maintains the contracts facing outward to clients.
When You Do Not Need a Dedicated Orchestration Layer
Not every composable system needs a dedicated orchestration platform. There is a genuine threshold below which building your own orchestration logic in application code is the right choice. If your composable system has three or four services, all owned by the same team, with simple composition requirements and low traffic, the investment in a dedicated orchestration layer may not be justified.
The threshold at which a dedicated orchestration layer pays off is roughly: five or more services whose data is regularly composed together, multiple client channels with different data requirements, traffic above a few hundred requests per second (at which point connection pooling and caching start to matter), and on-call responsibility for cross-service failures. Below these thresholds, the overhead of learning and operating an orchestration platform may outweigh the benefits. Above them, the alternative — maintaining cross-service coordination logic scattered across client code and bespoke BFF services — compounds into a significant ongoing maintenance burden.
Where to Start: Introducing Orchestration Incrementally
The most practical approach to introducing an orchestration layer into an existing composable system is incremental. Identify the two or three workflows that are most painful today: the highest-traffic user-facing flows, the ones with the most point-to-point connections, or the ones that generate the most on-call incidents because cross-service failures are hard to diagnose.
Migrate those workflows to the orchestration layer first. The immediate benefits — parallel execution, unified observability, centralised failure handling — are tangible and visible without requiring a full system migration. Once those workflows are running reliably through the orchestration layer, the case for migrating the next set of workflows is self-evident.
The strangler fig pattern works naturally here. The orchestration layer runs alongside existing point-to-point connections, gradually taking over coordination responsibility as workflows are migrated. Existing services do not need to change — the orchestration layer calls them exactly as any other consumer would. The migration is at the coordination layer, not the service layer, which means it can proceed at whatever pace fits your team's capacity.
Once a composable system has a working orchestration layer for its core workflows, the operational experience changes substantially. New features that require composing data from multiple services are built as orchestration workflows rather than hand-coded client-side coordination. Cross-service performance issues are diagnosed in the orchestration execution log rather than through multi-service log correlation. Upstream API changes are absorbed at the orchestration layer rather than requiring coordinated updates across multiple consumers. The composable architecture finally delivers what it promised: independent services that can be assembled into cohesive user experiences without coupling the teams that build them.
Related reading
- Building Modern BFF Layers: Backend-for-Frontend Architecture — how to structure channel-specific orchestration for different clients
- BFF Characteristics: Parallel Execution, Caching, Observability & Alerts — the production-readiness checklist for any orchestration layer
- The Hidden Cost of Point-to-Point Integrations — why direct service-to-service connections compound into a serious problem
- Composable Commerce Architecture: Building Modern E-Commerce Platforms — applying these orchestration patterns specifically to e-commerce
Service Composition
Coordinate multiple composable services into unified APIs. Apitide orchestrates service calls in parallel, merges results, and transforms data to create cohesive endpoints that hide the complexity of service composition from client applications.
Channel-Specific BFF Layers
Build dedicated BFF layers that compose data from composable services for specific channels. Mobile apps, web dashboards, and partner integrations each receive optimized data shapes while sharing the same underlying composable service architecture.
Cross-Service Observability
Monitor interactions between composable services with comprehensive execution logs and analytics. Understand how services compose together, identify performance bottlenecks, and debug issues across service boundaries in a single timeline view.
Independent Service Evolution
Evolve composable services independently without breaking client applications. Apitide's orchestration layer absorbs service changes, allowing teams to update individual services while maintaining backward compatibility at the API level.
Ready to build composable systems?
Start orchestrating your composable services with Apitide's synchronous API orchestration platform.